@@ -20,24 +20,69 @@ use crate::ptr;
20
20
///
21
21
/// # Example
22
22
///
23
- /// ```no_run
24
- /// use std::alloc::{GlobalAlloc, Layout, alloc};
23
+ /// ```
24
+ /// use std::alloc::{GlobalAlloc, Layout};
25
+ /// use std::cell::UnsafeCell;
25
26
/// use std::ptr::null_mut;
27
+ /// use std::sync::atomic::{
28
+ /// AtomicUsize,
29
+ /// Ordering::{Acquire, SeqCst},
30
+ /// };
26
31
///
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
32
37
/// }
33
38
///
34
39
/// #[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
+ /// };
36
44
///
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)
40
78
/// }
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);
41
86
/// }
42
87
/// ```
43
88
///
0 commit comments