clt_database/alloc/
backend.rs1use std::{fmt, ptr::NonNull, sync::OnceLock};
2
3use super::{api, AllocError, Layout, TursoAllocator};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum SetAllocatorError {
7 AlreadyInitialized,
8}
9
10impl fmt::Display for SetAllocatorError {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 match self {
13 Self::AlreadyInitialized => f.write_str("Turso allocator is already initialized"),
14 }
15 }
16}
17
18impl std::error::Error for SetAllocatorError {}
19
20pub unsafe trait TursoAllocBackend: Sync {
27 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
28
29 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout);
34}
35
36struct DefaultBackend;
37
38unsafe impl TursoAllocBackend for DefaultBackend {
39 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
40 <api::Global as api::ApiAllocator>::allocate(&api::Global, layout)
41 }
42
43 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
44 unsafe {
45 <api::Global as api::ApiAllocator>::deallocate(&api::Global, ptr, layout);
46 }
47 }
48}
49
50static DEFAULT_BACKEND: DefaultBackend = DefaultBackend;
51static BACKEND: OnceLock<&'static dyn TursoAllocBackend> = OnceLock::new();
52
53pub unsafe fn set_allocator(
64 backend: &'static dyn TursoAllocBackend,
65) -> Result<(), SetAllocatorError> {
66 BACKEND
67 .set(backend)
68 .map_err(|_| SetAllocatorError::AlreadyInitialized)
69}
70
71fn backend() -> &'static dyn TursoAllocBackend {
72 BACKEND.get().copied().unwrap_or(&DEFAULT_BACKEND)
73}
74
75unsafe impl api::ApiAllocator for TursoAllocator {
76 fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
77 backend().allocate(layout)
78 }
79
80 unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
81 unsafe {
82 backend().deallocate(ptr, layout);
83 }
84 }
85}