1#![allow(dead_code)]
3
4use core::{
5 cell::UnsafeCell,
6 marker::PhantomData,
7 mem::MaybeUninit,
8 num::NonZeroUsize,
9 ops::{Deref, DerefMut, Range},
10 ptr::{self, write},
11};
12
13use crate::{sync::spinlock::SpinLocked, types::bitset::BitAlloc};
14
15pub struct FixedPoolRef<'a, T, const N: usize, const WORDS: usize> {
16 idx: usize,
17 pool: &'a FixedPool<T, N, WORDS>,
18 _marker: PhantomData<T>,
19}
20
21impl<'a, T, const N: usize, const WORDS: usize> Deref for FixedPoolRef<'a, T, N, WORDS> {
22 type Target = T;
23
24 fn deref(&self) -> &Self::Target {
25 unsafe { &*self.pool.access(self.idx) }
28 }
29}
30
31impl<'a, T, const N: usize, const WORDS: usize> DerefMut for FixedPoolRef<'a, T, N, WORDS> {
32 fn deref_mut(&mut self) -> &mut Self::Target {
33 unsafe { &mut *self.pool.access(self.idx) }
36 }
37}
38
39impl<T, const N: usize, const WORDS: usize> Drop for FixedPoolRef<'_, T, N, WORDS> {
40 fn drop(&mut self) {
41 unsafe { ptr::drop_in_place(self.pool.access(self.idx)) };
43 self.pool.free(self.idx);
44 }
45}
46
47pub struct FixedPool<T, const N: usize, const WORDS: usize> {
48 free: SpinLocked<BitAlloc<WORDS>>,
49 blocks: [UnsafeCell<MaybeUninit<T>>; N],
50}
51
52impl<T, const N: usize, const WORDS: usize> FixedPool<T, N, WORDS> {
53 pub const fn new() -> Self {
54 Self {
55 free: SpinLocked::new(BitAlloc::from_array([!0usize; WORDS])),
56 blocks: [const { UnsafeCell::new(MaybeUninit::uninit()) }; N],
57 }
58 }
59
60 pub fn alloc(&self, new: T) -> Option<FixedPoolRef<'_, T, N, WORDS>> {
61 let mut alloc = self.free.lock();
65 let idx = alloc.alloc(1)?;
66 if idx >= N {
69 alloc.free(idx, 1);
70 return None;
71 }
72 drop(alloc);
73 let ptr = self.blocks[idx].get();
74 unsafe { ptr.write(MaybeUninit::new(new)) };
76 Some(FixedPoolRef {
77 idx,
78 pool: self,
79 _marker: PhantomData,
80 })
81 }
82
83 fn access(&self, idx: usize) -> *mut T {
84 self.blocks[idx].get() as *mut T
85 }
86
87 fn free(&self, idx: usize) {
88 self.free.lock().free(idx, 1);
89 }
90}
91
92struct SizedPoolMeta {
94 _size: usize,
95 next: Option<NonZeroUsize>,
96}
97
98#[deprecated(note = "Will be removed soon. Do not use!")]
100pub struct SizedPool<T: Default> {
101 head: Option<NonZeroUsize>,
102 _marker: PhantomData<T>,
103}
104
105#[allow(deprecated)]
106impl<T: Default> Default for SizedPool<T> {
107 fn default() -> Self {
108 Self::new()
109 }
110}
111
112#[allow(deprecated)]
113impl<T: Default> SizedPool<T> {
114 pub const fn new() -> Self {
116 Self {
117 head: None,
118 _marker: PhantomData,
119 }
120 }
121
122 const fn align_up() -> usize {
124 let meta = size_of::<SizedPoolMeta>();
125 let align = align_of::<T>();
126 (align - (meta % align)) % align
128 }
129
130 pub unsafe fn add_range(&mut self, range: Range<usize>) {
138 let mut ptr = range.start;
139
140 while ptr < range.end {
141 unsafe {
142 self.add_block(ptr);
143 }
144
145 ptr += Self::align_up() + size_of::<SizedPoolMeta>() + size_of::<T>();
146 }
147 }
148
149 unsafe fn add_block(&mut self, ptr: usize) {
157 let meta = SizedPoolMeta {
158 _size: size_of::<T>(),
159 next: self.head,
160 };
161
162 unsafe {
163 write(ptr as *mut SizedPoolMeta, meta);
164 }
165
166 self.head = Some(unsafe { NonZeroUsize::new_unchecked(ptr) });
167 }
168
169 pub fn alloc(&mut self) -> Option<Owned<T>> {
173 let head = self.head.take();
174
175 head.map(|head| {
176 let meta = unsafe { &*(head.get() as *const SizedPoolMeta) };
177 self.head = meta.next;
178
179 let ptr = head.get() + size_of::<SizedPoolMeta>() + Self::align_up();
180 unsafe { write(ptr as *mut T, T::default()) };
181
182 Owned { ptr: ptr as *mut T }
183 })
184 }
185
186 pub fn dealloc(&mut self, block: Owned<T>) {
190 let ptr = block.ptr as usize - size_of::<SizedPoolMeta>() - Self::align_up();
191
192 let head = self
194 .head
195 .replace(unsafe { NonZeroUsize::new_unchecked(ptr) });
196
197 let meta = unsafe { &mut *(ptr as *mut SizedPoolMeta) };
199 meta.next = head;
200 }
201}
202
203pub struct Owned<T> {
205 ptr: *mut T,
206}
207
208impl<T: Default> Deref for Owned<T> {
209 type Target = T;
210
211 fn deref(&self) -> &Self::Target {
212 unsafe { &*self.ptr }
213 }
214}
215
216impl<T: Default> DerefMut for Owned<T> {
217 fn deref_mut(&mut self) -> &mut Self::Target {
218 unsafe { &mut *self.ptr }
219 }
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn fixed_pool_alloc_beyond_n_returns_none() {
228 let pool: FixedPool<u32, 4, 1> = FixedPool::new();
229 let _r0 = pool.alloc(0).unwrap();
230 let _r1 = pool.alloc(1).unwrap();
231 let _r2 = pool.alloc(2).unwrap();
232 let _r3 = pool.alloc(3).unwrap();
233 assert!(pool.alloc(4).is_none());
234 }
235}