1use std::{alloc::{alloc, dealloc, Layout}, cell::UnsafeCell, ops::{Deref, DerefMut}, ptr::NonNull};
4
5pub mod sync;
6
7pub struct ArenaRefMut<'a, T: Sized> {
8 wr_counter: &'a UnsafeCell<i32>,
9 data: &'a UnsafeCell<T>
10}
11
12impl<T: Sized> Deref for ArenaRefMut<'_, T> {
13 type Target = T;
14
15 fn deref(&self) -> &Self::Target {
16 unsafe {
17 self.data.get().as_ref().unwrap()
18 }
19 }
20}
21
22impl<T: Sized> DerefMut for ArenaRefMut<'_, T> {
23 fn deref_mut(&mut self) -> &mut Self::Target {
24 unsafe {
25 self.data.get().as_mut().unwrap()
26 }
27 }
28}
29
30
31impl<T: Sized> Drop for ArenaRefMut<'_, T> {
32 fn drop(&mut self) {
33 unsafe {
34 *self.wr_counter.get() += 1;
35 }
36 }
37}
38
39
40pub struct ArenaRef<'a, T: Sized> {
41 wr_counter: &'a UnsafeCell<i32>,
42 data: &'a UnsafeCell<T>
43}
44
45impl<T: Sized> Deref for ArenaRef<'_, T> {
46 type Target = T;
47
48 fn deref(&self) -> &Self::Target {
49 unsafe {
50 self.data.get().as_ref().unwrap()
51 }
52 }
53}
54
55impl<T: Sized> Drop for ArenaRef<'_, T> {
56 fn drop(&mut self) {
57 unsafe {
58 *self.wr_counter.get() -= 1;
59 }
60 }
61}
62
63struct Entry<T: Sized> {
64 wr_counter: UnsafeCell<i32>,
65 data: UnsafeCell<T>
66}
67
68impl<T: Sized> Entry<T> {
69 pub fn new(data: T) -> Self {
70 Self {
71 wr_counter: UnsafeCell::new(0),
72 data: UnsafeCell::new(data)
73 }
74 }
75
76
77 pub fn borrow(&self) -> Option<ArenaRef<'_, T>> {
78 unsafe {
79 if *(self.wr_counter.get()) < 0 {
80 return None
81 }
82
83 *self.wr_counter.get() += 1;
84 }
85
86 return Some(ArenaRef {
87 wr_counter: &self.wr_counter,
88 data: &self.data
89 })
90 }
91
92 pub fn borrow_mut(&self) -> Option<ArenaRefMut<'_, T>> {
93 unsafe {
94 if *(self.wr_counter.get()) != 0 {
95 return None
96 }
97
98 *self.wr_counter.get() -= 1;
99 }
100
101 Some(ArenaRefMut { wr_counter: &self.wr_counter, data: &self.data })
102 }
103}
104
105struct Bucket<T: Sized> {
106 head: NonNull<Entry<T>>,
107 tail: NonNull<Entry<T>>,
108 last: Option<NonNull<Entry<T>>>,
109 layout: Layout
110}
111
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
113struct ArenaCellId(usize);
114
115impl From<usize> for ArenaCellId {
116 fn from(value: usize) -> Self {
117 Self(value)
118 }
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
122struct ArenaBucketId(usize);
123
124impl From<usize> for ArenaBucketId {
125 fn from(value: usize) -> Self {
126 Self(value)
127 }
128}
129
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd)]
131pub struct ArenaId {
132 block_id: ArenaBucketId,
133 cell_id: ArenaCellId
134}
135
136impl Ord for ArenaId {
137 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
138 if self.block_id != other.block_id {
139 return self.block_id.cmp(&other.block_id);
140 }
141
142 return self.cell_id.cmp(&other.cell_id);
143 }
144}
145
146impl ArenaId {
147 fn new<ABI, ACI>(block_id: ABI, cell_id: ACI) -> Self
148 where ArenaBucketId: From<ABI>, ArenaCellId: From<ACI>
149 {
150 Self {block_id: block_id.into(), cell_id: cell_id.into()}
151 }
152
153 fn next_block(&self) -> Self {
154 Self::new(self.block_id.0 + 1, 0)
155 }
156}
157
158impl<T: Sized> Drop for Bucket<T> {
159 fn drop(&mut self) {
160 unsafe {
161 if let Some(last) = self.last {
162 let mut cursor = self.head;
163
164 while cursor <= last {
165 cursor.drop_in_place();
166 cursor = cursor.add(1);
167 }
168
169 }
170
171 dealloc(self.head.cast::<u8>().as_ptr(), self.layout);
172 }
173 }
174}
175
176impl<T: Sized> Bucket<T> {
177 fn new(size: usize) -> Self {
178 unsafe {
179 let layout = Layout::array::<Entry<T>>(size).unwrap();
180 let head = NonNull::new(alloc(layout) as *mut Entry<T>).unwrap();
181 let tail = head.add(size - 1);
182 let last = None;
183 Self {head, tail, last, layout}
184 }
185 }
186
187 fn first_id(&self) -> Option<ArenaCellId> {
188 if self.len() == 0 {
189 return None
190 }
191
192 return Some(ArenaCellId(0))
193 }
194
195 fn next_id(&self, id: ArenaCellId) -> Option<ArenaCellId> {
196 self.last.map(|last| {
197 unsafe {
198 let cursor = self.head.add(id.0 + 1);
199 (cursor <= last).then(|| ArenaCellId(id.0 + 1))
200 }
201 }).flatten()
202 }
203
204 fn alloc(&mut self, value: T) -> ArenaCellId {
205 if self.is_full() {
206 panic!("block is full")
207 }
208
209 unsafe {
210 let mut last = self.last
211 .map(|last| last.add(1))
212 .unwrap_or_else(|| self.head);
213
214 *last.as_mut() = Entry::new(value);
215 self.last = Some(last);
216 return ArenaCellId(self.len() - 1)
217 }
218 }
219
220 fn len(&self) -> usize {
221 self.last.map(|last| {
222 unsafe {
223 let offset: usize = last.offset_from(self.head).try_into().unwrap();
224 offset + 1
225 }
226 }).unwrap_or_default()
227 }
228
229 fn get_cell(&self, cell_id: ArenaCellId) -> Option<&Entry<T>> {
231 self.last
232 .map(|last| {
233 unsafe {
234 let ptr = self.head.add(cell_id.0);
235
236 (ptr <= last && ptr >= self.head)
237 .then(|| ptr.as_ref())
238 }
239 }).flatten()
240 }
241
242 pub fn is_full(&self) -> bool {
243 self.last
244 .map(|last| last >= self.tail)
245 .unwrap_or_else(|| false)
246 }
247}
248
249
250pub struct ArenaIter<'a, T: Sized> {
251 arena: &'a Arena<T>,
252 id: Option<ArenaId>
253}
254
255impl<'a, T: Sized> ArenaIter<'a, T> {
256 pub fn new(arena: &'a Arena<T>) -> Self {
257 Self {
258 arena,
259 id: None
260 }
261 }
262}
263
264impl<'a, T: Sized> Iterator for ArenaIter<'a, T> {
265 type Item = ArenaId;
266
267 fn next(&mut self) -> Option<Self::Item> {
268 if self.id.is_none() {
269 self.id = self.arena.first_id();
270 return self.id
271 }
272
273 let id = self.id.unwrap();
274 self.id = self.arena.next_id(id);
275 return self.id
276 }
277}
278
279pub struct Arena<T: Sized> {
295 blocks: Vec<Bucket<T>>,
296 block_size: usize
297}
298
299impl<T: Sized> Arena<T> {
300 pub fn new(block_size: usize) -> Self {
301 Self {
302 blocks: Vec::default(),
303 block_size
304 }
305 }
306
307 pub fn iter(&self) -> ArenaIter<'_, T> {
308 ArenaIter::new(self)
309 }
310
311 pub fn borrow(&self, id: ArenaId) -> Option<ArenaRef<'_, T>> {
312 self.get_cell(id)
313 .map(Entry::borrow)
314 .flatten()
315 }
316
317 pub fn borrow_mut(&self, id: ArenaId) -> Option<ArenaRefMut<'_, T>> {
318 self.get_cell(id).map(Entry::borrow_mut).flatten()
319 }
320
321 pub fn alloc(&mut self, data: T) -> ArenaId {
322 if let Some((block_id, block)) = self.find_free_block() {
323 let cell_id: ArenaCellId = block.alloc(data);
324 return ArenaId {block_id, cell_id}
325 }
326
327 let mut block = Bucket::<T>::new(self.block_size);
328 let cell_id = block.alloc(data);
329 self.blocks.push(block);
330 let block_id = ArenaBucketId(self.blocks.len() - 1);
331
332 return ArenaId { block_id, cell_id }
333 }
334
335 pub fn len(&self) -> usize {
336 self.blocks
337 .iter()
338 .map(|block| block.len())
339 .reduce(std::ops::Add::add)
340 .unwrap_or_default()
341 }
342
343 fn get_cell(&self, id: ArenaId) -> Option<&Entry<T>> {
344 self.blocks
345 .get(id.block_id.0)
346 .map(|block| block.get_cell(id.cell_id))
347 .flatten()
348 }
349
350 fn find_free_block(&mut self) -> Option<(ArenaBucketId, &mut Bucket<T>)> {
351 self.blocks
352 .iter_mut()
353 .enumerate()
354 .find(|(_, block)| !block.is_full())
355 .map(|(block_id, block)| (ArenaBucketId(block_id), block))
356 }
357
358 fn first_id(&self) -> Option<ArenaId> {
359 self.blocks
360 .get(0)
361 .map(|block|
362 block.first_id().map(|cell_id| ArenaId::new(0, cell_id))
363 )
364 .flatten()
365 }
366
367 fn next_block_id(&self, id: ArenaId) -> Option<ArenaId> {
368 self.blocks
369 .get(id.block_id.0 + 1)
370 .map(|block|
371 block.first_id()
372 .map(|cell_id| ArenaId::new(
373 id.block_id.0 + 1,
374 cell_id
375 ))
376 )
377 .flatten()
378 }
379
380 fn next_id(&self, id: ArenaId) -> Option<ArenaId> {
381 self.blocks
382 .get(id.block_id.0)
383 .map(|block| {
384 block
385 .next_id(id.cell_id)
386 .map(|cell_id| ArenaId::new(id.block_id, cell_id))
387 })
388 .flatten()
389 .or_else(|| self.next_block_id(id))
390
391 }
392}
393
394#[cfg(test)]
395mod tests {
396 use crate::{Arena, ArenaId};
397
398 #[test]
399 fn test_alloc() {
400 let mut arena = Arena::<u32>::new(1);
401 let id = arena.alloc(10);
402
403 assert_eq!(arena.len(), 1);
404 assert!(arena.get_cell(ArenaId::new(0, 0)).is_some());
405
406 let cell = arena.get_cell(id).unwrap();
407 assert_eq!(*cell.borrow().unwrap(), 10);
408 }
409
410 #[test]
411 fn test_must_create_another_block_if_previous_is_full() {
412 let mut arena = Arena::<u32>::new(2);
413 arena.alloc(1);
414 arena.alloc(2);
415 let id = arena.alloc(3);
416 arena.alloc(4);
417
418 assert_eq!(arena.len(), 4);
419
420 let cell = arena.get_cell(id).unwrap();
421 assert_eq!(*cell.borrow().unwrap(), 3);
422 }
423
424 #[test]
425 fn test_iter() {
426 let mut arena = Arena::<u32>::new(2);
427 arena.alloc(1);
428 arena.alloc(2);
429 arena.alloc(3);
430 arena.alloc(4);
431
432 assert_eq!(arena.next_block_id(ArenaId::new(0,1)), Some(ArenaId::new(1,0)));
433 assert_eq!(arena.next_id(ArenaId::new(0,1)), Some(ArenaId::new(1,0)));
434
435 let expected_ids = vec![
436 ArenaId::new(0, 0),
437 ArenaId::new(0, 1),
438 ArenaId::new(1, 0),
439 ArenaId::new(1, 1)
440 ];
441
442 let ids = arena.iter().collect::<Vec<_>>();
443 assert_eq!(expected_ids, ids)
444 }
445
446 #[test]
447 fn test_can_borrow_multiple_times() {
448 let mut arena = Arena::<u32>::new(1);
449 let id = arena.alloc(10);
450
451 let borrow_1 = arena.borrow(id);
452 let borrow_2 = arena.borrow(id);
453
454 assert!(borrow_1.is_some());
455 assert!(borrow_2.is_some())
456 }
457
458 #[test]
459 fn test_cannot_mut_borrow_if_already_borrowed() {
460 let mut arena = Arena::<u32>::new(1);
461 let id = arena.alloc(10);
462
463 let _ref = arena.borrow(id).unwrap();
464 assert_eq!(arena.borrow_mut(id).is_none(), true); }
466
467 #[test]
468 fn test_cannot_mut_borrow_multiple_times() {
469 let mut arena = Arena::<u32>::new(1);
470 let id = arena.alloc(10);
471
472 let _mut_ref = arena.borrow_mut(id).unwrap();
473 assert_eq!(arena.borrow_mut(id).is_none(), true); }
475
476 #[test]
477 fn test_can_mut_borrow_two_different_entries() {
478 let mut arena = Arena::<u32>::new(2);
479 let id_1 = arena.alloc(10);
480 let id_2 = arena.alloc(20);
481
482 let ref_1 = arena.borrow_mut(id_1).unwrap();
483 let ref_2 = arena.borrow_mut(id_2).unwrap();
484
485 assert_eq!(*ref_1, 10);
486 assert_eq!(*ref_2, 20);
487 }
488
489 pub struct DropCanary<'a> {
490 flag: Option<&'a mut bool>
491 }
492
493 impl<'a> Drop for DropCanary<'a> {
494 fn drop(&mut self) {
495 if let Some(f) = &mut self.flag {
496 **f = true;
497 }
498 }
499 }
500
501 #[test]
502 fn test_drop() {
503 let mut flag = false;
504 let mut arena = Arena::<DropCanary>::new(2);
505
506 let id = arena.alloc(DropCanary { flag: Some(&mut flag)});
507
508 assert_eq!(arena.borrow(id).unwrap().flag, Some(&mut false));
509 drop(arena);
510
511 assert_eq!(flag, true);
512 }
513}