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; } } } }