silly_alloc/bump/
head.rs

1/*!
2Heads track where the first free byte in an arena is.
3*/
4
5use core::{
6    cell::UnsafeCell,
7    sync::atomic::{AtomicUsize, Ordering},
8};
9
10/// The head is the pointer that gets bumped in a bump allocator.
11/// It tracks of how many bytes have been marked as in-use.
12pub trait Head {
13    fn num_bytes_used(&self) -> usize;
14    fn bump(&self, inc: usize);
15    fn set(&self, v: usize);
16}
17
18pub struct ThreadSafeHead(AtomicUsize);
19
20impl ThreadSafeHead {
21    pub const fn new() -> Self {
22        ThreadSafeHead(AtomicUsize::new(0))
23    }
24}
25
26impl Head for ThreadSafeHead {
27    fn num_bytes_used(&self) -> usize {
28        self.0.load(Ordering::SeqCst)
29    }
30
31    fn bump(&self, inc: usize) {
32        self.0.fetch_add(inc, Ordering::SeqCst);
33    }
34
35    fn set(&self, v: usize) {
36        self.0.store(v, Ordering::SeqCst);
37    }
38}
39
40impl Default for ThreadSafeHead {
41    fn default() -> Self {
42        ThreadSafeHead(AtomicUsize::new(0))
43    }
44}
45
46pub struct SingleThreadedHead(UnsafeCell<usize>);
47
48unsafe impl Sync for SingleThreadedHead {}
49
50impl SingleThreadedHead {
51    pub const fn new() -> Self {
52        SingleThreadedHead(UnsafeCell::new(0))
53    }
54}
55
56impl Head for SingleThreadedHead {
57    fn num_bytes_used(&self) -> usize {
58        unsafe { *self.0.get() }
59    }
60
61    fn bump(&self, inc: usize) {
62        unsafe {
63            *self.0.get() = self.num_bytes_used() + inc;
64        }
65    }
66
67    fn set(&self, v: usize) {
68        unsafe {
69            *self.0.get() = v;
70        }
71    }
72}
73
74impl Default for SingleThreadedHead {
75    fn default() -> Self {
76        SingleThreadedHead(UnsafeCell::new(0))
77    }
78}