twizzler/
alloc.rs

1use std::{
2    alloc::{AllocError, Layout},
3    mem::MaybeUninit,
4};
5
6use crate::ptr::{GlobalPtr, RefMut};
7
8pub mod arena;
9mod global;
10pub mod invbox;
11
12pub use global::OwnedGlobalPtr;
13
14/// Basic allocation trait.
15pub trait Allocator: Clone {
16    /// Allocate based on layout within this allocator. Returns a global pointer
17    /// to the start of the allocation.
18    ///
19    /// Note: Using this function by itself can leak memory, particularly on failure.
20    /// Users should consider using InvBox instead.
21    fn alloc(&self, layout: Layout) -> Result<GlobalPtr<u8>, AllocError>;
22
23    /// Allocate based on layout within this allocator. Returns a global pointer
24    /// to the start of the allocation.
25    ///
26    /// Note: Using this function by itself can leak memory, particularly on failure.
27    /// Users should consider using InvBox instead.
28    fn alloc_with<T>(
29        &self,
30        f: impl FnOnce(RefMut<MaybeUninit<T>>) -> Result<RefMut<T>, AllocError>,
31    ) -> Result<GlobalPtr<u8>, AllocError> {
32        let res = self.alloc(Layout::new::<T>())?;
33        let res = res.cast::<MaybeUninit<T>>();
34        let res = unsafe { res.resolve_mut() };
35        Ok(f(res)?.global().cast())
36    }
37
38    /// Free an allocation.
39    ///
40    /// # Safety
41    /// Caller must ensure that the pointer is valid and was allocated by this allocator, and
42    /// refers to memory that matches the provided layout.
43    unsafe fn dealloc(&self, ptr: GlobalPtr<u8>, layout: Layout);
44
45    /// Reallocate an allocation.
46    ///
47    /// # Safety
48    /// Caller must ensure that the pointer is valid and was allocated by this allocator, and
49    /// refers to memory that matches the provided layout.
50    unsafe fn realloc(
51        &self,
52        ptr: GlobalPtr<u8>,
53        layout: Layout,
54        newsize: usize,
55    ) -> Result<GlobalPtr<u8>, AllocError> {
56        let new_layout =
57            Layout::from_size_align(newsize, layout.align()).map_err(|_| AllocError)?;
58
59        let new_alloc = self.alloc(new_layout)?;
60        unsafe {
61            if !ptr.is_null() {
62                let new_res = new_alloc.resolve_mut();
63                let old_res = ptr.resolve_mut();
64                let copy_len = std::cmp::min(layout.size(), new_layout.size());
65                new_res.raw().copy_from(old_res.raw(), copy_len);
66            }
67        }
68        Ok(new_alloc)
69    }
70}
71
72/// Allocator ensures that all allocations will take place within one object.
73pub trait SingleObjectAllocator {}