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
use crossbeam_epoch::{Atomic, Owned}; use std::ops::Deref; use std::{marker::PhantomData, sync::atomic::Ordering}; const fn drop_outer(flag: u8) -> u8 { flag & 0b10 } #[derive(Debug)] pub struct Outer<T> { flag_ptr: usize, data_ptr: usize, _type: PhantomData<T>, } impl<T> Deref for Outer<T> { type Target = T; fn deref(&self) -> &Self::Target { unsafe { &*(self.data_ptr as *const T) } } } impl<T> Drop for Outer<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_outer(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; } } } } impl<T> Outer<T> { pub(crate) const fn new(flag_ptr: usize, data_ptr: usize) -> Self { Self { flag_ptr, data_ptr, _type: PhantomData, } } }