nanvm_lib/mem/
block_header.rs

1use 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    // required
15    unsafe fn ref_counter_update(&self, i: RefCounterUpdate) -> isize;
16    //
17    #[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}