lifetime_thread/
outer.rs

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