nanvm_lib/mem/
block_header.rs1use core::{
2 cell::Cell,
3 sync::atomic::{AtomicIsize, Ordering},
4};
5
6use crate::{
7 common::ref_mut::RefMut,
8 mem::{manager::Dealloc, object::Object, ref_counter_update::RefCounterUpdate},
9};
10
11use super::block::Block;
12
13pub trait BlockHeader: Default + Sized {
14 unsafe fn ref_counter_update(&self, i: RefCounterUpdate) -> isize;
16 #[inline(always)]
18 unsafe fn block<T: Object, D: Dealloc>(&mut self) -> &mut Block<T, D> {
19 &mut *(self.to_mut_ptr() as *mut _)
20 }
21}
22
23impl BlockHeader for AtomicIsize {
24 #[inline(always)]
25 unsafe fn ref_counter_update(&self, val: RefCounterUpdate) -> isize {
26 self.fetch_add(val as isize, Ordering::Relaxed)
27 }
28}
29
30impl BlockHeader for Cell<isize> {
31 #[inline(always)]
32 unsafe fn ref_counter_update(&self, val: RefCounterUpdate) -> isize {
33 let result = self.get();
34 self.set(result + val as isize);
35 result
36 }
37}
38
39#[cfg(test)]
40mod test {
41 use core::{
42 cell::Cell,
43 sync::atomic::{AtomicIsize, Ordering},
44 };
45
46 use wasm_bindgen_test::wasm_bindgen_test;
47
48 use crate::mem::ref_counter_update::RefCounterUpdate;
49
50 use super::BlockHeader;
51
52 #[test]
53 #[wasm_bindgen_test]
54 fn test_atomic() {
55 let x = AtomicIsize::default();
56 assert_eq!(x.load(Ordering::Relaxed), 0);
57 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::Read) }, 0);
58 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::AddRef) }, 0);
59 assert_eq!(
60 unsafe { x.ref_counter_update(RefCounterUpdate::Release) },
61 1
62 );
63 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::Read) }, 0);
64 assert_eq!(
65 unsafe { x.ref_counter_update(RefCounterUpdate::Release) },
66 0
67 );
68 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::Read) }, -1);
69 }
70
71 #[test]
72 #[wasm_bindgen_test]
73 fn test_cell() {
74 let x = Cell::default();
75 assert_eq!(x.get(), 0);
76 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::Read) }, 0);
77 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::AddRef) }, 0);
78 assert_eq!(
79 unsafe { x.ref_counter_update(RefCounterUpdate::Release) },
80 1
81 );
82 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::Read) }, 0);
83 assert_eq!(
84 unsafe { x.ref_counter_update(RefCounterUpdate::Release) },
85 0
86 );
87 assert_eq!(unsafe { x.ref_counter_update(RefCounterUpdate::Read) }, -1);
88 }
89}