@@ -20,24 +20,69 @@ use crate::ptr;
2020///
2121/// # Example
2222///
23- /// ```no_run
24- /// use std::alloc::{GlobalAlloc, Layout, alloc};
23+ /// ```
24+ /// use std::alloc::{GlobalAlloc, Layout};
25+ /// use std::cell::UnsafeCell;
2526/// use std::ptr::null_mut;
27+ /// use std::sync::atomic::{
28+ /// AtomicUsize,
29+ /// Ordering::{Acquire, SeqCst},
30+ /// };
2631///
27- /// struct MyAllocator;
28- ///
29- /// unsafe impl GlobalAlloc for MyAllocator {
30- /// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
31- /// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
32+ /// const ARENA_SIZE: usize = 128 * 1024;
33+ /// const MAX_SUPPORTED_ALIGN: usize = 4096;
34+ /// #[repr(C, align(4096))] // 4096 == MAX_SUPPORTED_ALIGN
35+ /// struct SimpleAllocator {
36+ /// arena: UnsafeCell<[u8; ARENA_SIZE]>,
37+ /// remaining: AtomicUsize, // we allocate from the top, counting down
3238/// }
3339///
3440/// #[global_allocator]
35- /// static A: MyAllocator = MyAllocator;
41+ /// static ALLOCATOR: SimpleAllocator = SimpleAllocator {
42+ /// arena: UnsafeCell::new([0x55; ARENA_SIZE]),
43+ /// remaining: AtomicUsize::new(ARENA_SIZE),
44+ /// };
3645///
37- /// fn main() {
38- /// unsafe {
39- /// assert!(alloc(Layout::new::<u32>()).is_null())
46+ /// unsafe impl Sync for SimpleAllocator {}
47+ ///
48+ /// unsafe impl GlobalAlloc for SimpleAllocator {
49+ /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
50+ /// let size = layout.size();
51+ /// let align = layout.align();
52+ ///
53+ /// // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.
54+ /// // So we can safely use a mask to ensure alignment without worrying about UB.
55+ /// let align_mask_to_round_down = !(align - 1);
56+ ///
57+ /// if align > MAX_SUPPORTED_ALIGN {
58+ /// return null_mut();
59+ /// }
60+ ///
61+ /// let mut allocated = 0;
62+ /// if self
63+ /// .remaining
64+ /// .fetch_update(SeqCst, SeqCst, |mut remaining| {
65+ /// if size > remaining {
66+ /// return None;
67+ /// }
68+ /// remaining -= size;
69+ /// remaining &= align_mask_to_round_down;
70+ /// allocated = remaining;
71+ /// Some(remaining)
72+ /// })
73+ /// .is_err()
74+ /// {
75+ /// return null_mut();
76+ /// };
77+ /// (self.arena.get() as *mut u8).add(allocated)
4078/// }
79+ /// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
80+ /// }
81+ ///
82+ /// fn main() {
83+ /// let _s = format!("allocating a string!");
84+ /// let currently = ALLOCATOR.remaining.load(Acquire);
85+ /// println!("allocated so far: {}", ARENA_SIZE - currently);
4186/// }
4287/// ```
4388///
0 commit comments