extern crate core; use std::sync::atomic::AtomicBool; use std::mem::transmute; use std::sync::atomic::Ordering; pub struct Observer { hidden: Option<*const HiddenState> } pub struct Observable { hidden: Option<*const HiddenState> } struct HiddenState { observer: AtomicBool, observable: AtomicBool, } impl Observable { pub fn new() -> (Observer, Observable) { let state = Box::new(HiddenState { observable: AtomicBool::new(true), observer: AtomicBool::new(true), }); let raw_state: *const HiddenState; unsafe { // This pointer is now an indefinitely valid static reference. raw_state = transmute(state); } let observer = Observer { hidden: Some(raw_state) }; let observable = Observable { hidden: Some(raw_state) }; return (observer, observable); } // This is safe because no other mutable references can exist of HiddenState::observable fn atomic_state(&mut self) -> &mut AtomicBool { unsafe { let state_ref = self.immutable_state(); let atomic_state_ref = &state_ref.observable as *const AtomicBool; return &mut (*(atomic_state_ref as *mut AtomicBool)); } } // This is safe because it returns an immutable reference fn immutable_state(&mut self) -> &HiddenState { unsafe { let state_ref = &(**(self.hidden.as_ref().unwrap())); return state_ref; } } } impl Observer { // This is safe because no other mutable references can exist of HiddenState::observer fn atomic_state(&mut self) -> &mut AtomicBool { unsafe { let state_ref = self.immutable_state(); let atomic_state_ref = &state_ref.observer as *const AtomicBool; return &mut (*(atomic_state_ref as *mut AtomicBool)); } } // This is safe because it returns an immutable reference fn immutable_state(&mut self) -> &HiddenState { unsafe { let state_ref = &(**(self.hidden.as_ref().unwrap())); return state_ref; } } } impl HiddenState { fn should_drop(&self) -> bool { return !self.observer.fetch_or(self.observable.load(Ordering::Acquire), Ordering::Acquire); } } impl Drop for Observable { fn drop(&mut self) { self.atomic_state().store(false, Ordering::Acquire); if self.immutable_state().should_drop() { unsafe { transmute::<*const HiddenState, Box>(self.hidden.take().unwrap()); } } } } impl Drop for Observer { fn drop(&mut self) { self.atomic_state().store(false, Ordering::Acquire); if self.immutable_state().should_drop() { unsafe { transmute::<*const HiddenState, Box>(self.hidden.take().unwrap()); } } } }