static_alloc/unsync/
chain.rs1use core::{
4 alloc::{Layout, LayoutError},
5 cell::Cell,
6 mem::MaybeUninit,
7 ptr::{self, NonNull},
8};
9
10use alloc::{alloc::alloc_zeroed, boxed::Box};
11
12use crate::bump::Failure;
13use crate::leaked::LeakBox;
14use crate::unsync::bump::BumpSlice;
15
16#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
19pub struct TryNewError {
20 inner: RawAllocError,
21}
22
23impl TryNewError {
24 pub const fn allocation_size(&self) -> usize {
27 self.inner.allocation_size()
28 }
29}
30
31type LinkPtr = Option<NonNull<Link>>;
32
33struct Link {
34 next: Cell<LinkPtr>,
38 bump: BumpSlice,
40}
41
42pub struct Chain {
46 root: Cell<LinkPtr>,
49}
50
51impl Chain {
52 pub fn new(size: usize) -> Result<Self, TryNewError> {
55 let link = Link::alloc(size).map_err(|e| TryNewError { inner: e })?;
56 Ok(Chain {
57 root: Cell::new(Some(link)),
58 })
59 }
60
61 pub fn bump_box<'bump, T: 'bump>(
63 &'bump self,
64 ) -> Result<LeakBox<'bump, MaybeUninit<T>>, Failure> {
65 let root = self.root().ok_or(Failure::Exhausted)?;
66 root.as_bump().bump_box()
67 }
68
69 pub fn chain(&self, new: Chain) {
75 let self_bump = self.root.take();
77
78 match new.root() {
79 None => self.root.set(self_bump),
80 Some(root) => {
81 unsafe { root.set_next(self_bump) };
82 self.root.set(new.root.take())
83 }
84 }
85 }
86
87 pub fn capacity(&self) -> usize {
91 match self.root() {
92 None => 0,
93 Some(root) => root.as_bump().capacity(),
94 }
95 }
96
97 pub fn remaining_capacity(&self) -> usize {
101 match self.root() {
102 None => 0,
103 Some(root) => self.capacity() - root.as_bump().level().0,
104 }
105 }
106
107 fn root(&self) -> Option<&Link> {
108 unsafe {
109 let bump_ptr = self.root.get()?.as_ptr();
110 Some(&*bump_ptr)
111 }
112 }
113}
114
115#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
118pub(crate) struct RawAllocError {
119 allocation_size: usize,
120 kind: RawAllocFailure,
121}
122
123#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
124enum RawAllocFailure {
125 Exhausted,
126 Layout,
127}
128
129impl Link {
130 pub(crate) unsafe fn set_next(&self, next: LinkPtr) {
135 if let Some(next) = self.next.replace(next) {
136 let _ = unsafe { Box::from_raw(next.as_ptr()) };
138 }
139 }
140
141 pub(crate) fn take_next(&self) -> Option<Box<Link>> {
143 let ptr = self.next.take()?;
144 Some(unsafe { Box::from_raw(ptr.as_ptr()) })
146 }
147
148 pub(crate) fn as_bump(&self) -> &BumpSlice {
149 &self.bump
150 }
151
152 pub(crate) fn layout_from_size(size: usize) -> Result<Layout, LayoutError> {
153 Layout::new::<Cell<LinkPtr>>()
154 .extend(BumpSlice::layout_from_size(size)?)
155 .map(|layout| layout.0)
156 }
157
158 unsafe fn alloc_raw(layout: Layout) -> Result<NonNull<u8>, RawAllocError> {
159 let ptr = alloc_zeroed(layout);
160 NonNull::new(ptr)
161 .ok_or_else(|| RawAllocError::new(layout.size(), RawAllocFailure::Exhausted))
162 }
163
164 pub(crate) fn alloc(capacity: usize) -> Result<NonNull<Self>, RawAllocError> {
166 let layout = Self::layout_from_size(capacity)
167 .map_err(|_| RawAllocError::new(capacity, RawAllocFailure::Layout))?;
168
169 unsafe {
170 let raw = Link::alloc_raw(layout)?;
171 let raw_mut: *mut [Cell<MaybeUninit<u8>>] =
172 ptr::slice_from_raw_parts_mut(raw.cast().as_ptr(), capacity);
173 Ok(NonNull::new_unchecked(raw_mut as *mut Link))
174 }
175 }
176}
177
178impl RawAllocError {
179 const fn new(allocation_size: usize, kind: RawAllocFailure) -> Self {
180 Self {
181 allocation_size,
182 kind,
183 }
184 }
185
186 pub(crate) const fn allocation_size(&self) -> usize {
187 self.allocation_size
188 }
189}
190
191impl Drop for Chain {
193 fn drop(&mut self) {
194 let mut current = self.root.take();
195 while let Some(non_null) = current {
196 let link = unsafe { Box::from_raw(non_null.as_ptr()) };
198 current = link.next.take();
199 }
200 }
201}
202
203impl Drop for Link {
204 fn drop(&mut self) {
205 let mut current = self.take_next();
206 while let Some(link) = current {
207 current = link.take_next();
208 }
209 }
210}