#![allow(dead_code)] #[cfg(loom)] pub use loom::*; #[cfg(not(loom))] pub use std::{sync, thread}; pub use track_access::*; pub fn maybe_loom_model(test: F) where F: Fn() + Send + Sync + 'static, { #[cfg(loom)] loom::model(test); #[cfg(not(loom))] test(); } #[cfg(loom)] mod track_access { use loom::{alloc::Track, cell::UnsafeCell}; use std::{ borrow::Borrow, hash::{Hash, Hasher}, }; use flashmap::TrustedHashEq; pub struct TrackAccess(Track>>); unsafe impl TrustedHashEq for TrackAccess where Self: Hash + Eq {} impl TrackAccess { pub fn new(val: T) -> Self { Self(Track::new(Box::new(UnsafeCell::new(val)))) } pub fn get(&self) -> &T { self.0.get_ref().with(|ptr| unsafe { &*ptr }) } pub fn get_mut(&mut self) -> &mut T { self.0.get_ref().with_mut(|ptr| unsafe { &mut *ptr }) } } unsafe impl Sync for TrackAccess {} impl PartialEq for TrackAccess { fn eq(&self, other: &Self) -> bool { PartialEq::eq(self.get(), other.get()) } } impl Eq for TrackAccess {} impl Hash for TrackAccess { fn hash(&self, state: &mut H) { Hash::hash(self.get(), state) } } impl Borrow for TrackAccess { fn borrow(&self) -> &T { self.0.get_ref().with(|ptr| unsafe { &*ptr }) } } } #[cfg(not(loom))] mod track_access { use std::borrow::Borrow; use std::hash::Hash; use flashmap::TrustedHashEq; // The intent is that the tests are run with miri which will do the tracking through the box #[derive(PartialEq, Eq, Hash)] pub struct TrackAccess(Box); unsafe impl TrustedHashEq for TrackAccess where Self: Hash + Eq {} impl TrackAccess { pub fn new(val: T) -> Self { Self(Box::new(val)) } pub fn get(&self) -> &T { &self.0 } pub fn get_mut(&mut self) -> &mut T { &mut self.0 } } impl Borrow for TrackAccess { fn borrow(&self) -> &T { &self.0 } } }