1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crossbeam_epoch::{Atomic, Owned};
use std::{marker::PhantomData, sync::atomic::Ordering};

const fn drop_inner(flag: u8) -> u8 {
    flag & 0b01
}

const fn is_outer_live(flag: u8) -> bool {
    flag & 0b01 > 0
}

#[derive(Debug)]
pub struct Inner<T> {
    flag_ptr: usize,
    data_ptr: usize,
    _type: PhantomData<T>,
}

impl<T> Inner<T> {
    pub(crate) const fn new(flag_ptr: usize, data_ptr: usize) -> Self {
        Self {
            flag_ptr,
            data_ptr,
            _type: PhantomData,
        }
    }
    #[must_use]
    pub fn get(&self) -> Option<&T> {
        let guard = crossbeam_epoch::pin();
        let flag_ptr = unsafe { &*(self.flag_ptr as *const Atomic<u8>) };
        let flag = flag_ptr.load(Ordering::Acquire, &guard);
        let old = unsafe { *flag.deref() };
        if is_outer_live(old) {
            Some(unsafe { &*(self.data_ptr as *const T) })
        } else {
            None
        }
    }
}
impl<T> Drop for Inner<T> {
    fn drop(&mut self) {
        let guard = crossbeam_epoch::pin();
        let flag_ptr = unsafe { &*(self.flag_ptr as *const Atomic<u8>) };
        loop {
            let flag = flag_ptr.load(Ordering::Acquire, &guard);
            let old = unsafe { *flag.deref() };
            let n = drop_inner(old);

            if let Ok(t) = flag_ptr.compare_and_set(flag, Owned::new(n), Ordering::Release, &guard)
            {
                if n == 0 {
                    unsafe {
                        guard.defer_destroy(t);
                        std::ptr::drop_in_place(self.data_ptr as *mut T);
                    }
                }
                break;
            }
        }
    }
}