@@ -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+ /// #[repr(C, align(131072))] // 131072 == ARENA_SIZE.
34+ /// struct SimpleAllocator {
35+ /// arena: UnsafeCell<[u8; ARENA_SIZE]>,
36+ /// remaining: AtomicUsize, // we allocate from the top, counting down
3237/// }
3338///
3439/// #[global_allocator]
35- /// static A: MyAllocator = MyAllocator;
40+ /// static ALLOCATOR: SimpleAllocator = SimpleAllocator {
41+ /// arena: UnsafeCell::new([0x55; ARENA_SIZE]),
42+ /// remaining: AtomicUsize::new(ARENA_SIZE),
43+ /// };
3644///
37- /// fn main() {
38- /// unsafe {
39- /// assert!(alloc(Layout::new::<u32>()).is_null())
45+ /// unsafe impl Sync for SimpleAllocator {}
46+ ///
47+ /// unsafe impl GlobalAlloc for SimpleAllocator {
48+ /// unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
49+ /// let size = layout.size();
50+ /// let align = layout.align();
51+ ///
52+ /// // `Layout` contract forbids making a `Layout` with align=0, or align not power of 2.
53+ /// // So we can safely use a mask to ensure alignment without worrying about UB.
54+ /// let align_mask_to_round_down = !(align - 1);
55+ ///
56+ /// if align > ARENA_SIZE {
57+ /// // align may be > size !
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