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}