lifetime_thread/
inner.rs

1use crossbeam_epoch::{Atomic, Owned};
2use std::{marker::PhantomData, sync::atomic::Ordering};
3
4const fn drop_inner(flag: u8) -> u8 {
5    flag & 0b01
6}
7
8const fn is_outer_live(flag: u8) -> bool {
9    flag & 0b01 > 0
10}
11
12#[derive(Debug)]
13pub struct Inner<T> {
14    flag_ptr: usize,
15    data_ptr: usize,
16    _type: PhantomData<T>,
17}
18
19impl<T> Inner<T> {
20    pub(crate) const fn new(flag_ptr: usize, data_ptr: usize) -> Self {
21        Self {
22            flag_ptr,
23            data_ptr,
24            _type: PhantomData,
25        }
26    }
27    #[must_use]
28    pub fn get(&self) -> Option<&T> {
29        let guard = crossbeam_epoch::pin();
30        let flag_ptr = unsafe { &*(self.flag_ptr as *const Atomic<u8>) };
31        let flag = flag_ptr.load(Ordering::Acquire, &guard);
32        let old = unsafe { *flag.deref() };
33        if is_outer_live(old) {
34            Some(unsafe { &*(self.data_ptr as *const T) })
35        } else {
36            None
37        }
38    }
39}
40impl<T> Drop for Inner<T> {
41    fn drop(&mut self) {
42        let guard = crossbeam_epoch::pin();
43        let flag_ptr = unsafe { &*(self.flag_ptr as *const Atomic<u8>) };
44        loop {
45            let flag = flag_ptr.load(Ordering::Acquire, &guard);
46            let old = unsafe { *flag.deref() };
47            let n = drop_inner(old);
48
49            if let Ok(t) = flag_ptr.compare_and_set(flag, Owned::new(n), Ordering::Release, &guard)
50            {
51                if n == 0 {
52                    unsafe {
53                        guard.defer_destroy(t);
54                        std::ptr::drop_in_place(self.data_ptr as *mut T);
55                    }
56                }
57                break;
58            }
59        }
60    }
61}