//! A wrapper that is [`Sync`] for any value by granting only exclusive access to it. use core::fmt; /// A value reachable only through exclusive access, which makes the wrapper [`Sync`] whatever /// the value is. /// /// Every accessor takes `&mut self` or `self`, so a shared reference to the wrapper cannot reach /// the value. That is all `Sync` requires, which lets a value that is `Send` but not `Sync`, /// such as a boxed future, live in a type that must be `Sync`. pub struct Exclusive { inner: T, } // SAFETY: The value is reachable only through `&mut Exclusive` or by consuming the wrapper, // never through `&Exclusive`, so sharing the wrapper between threads cannot share the value. unsafe impl Sync for Exclusive {} impl Exclusive { /// Wrap `inner`. pub const fn new(inner: T) -> Self { Self { inner } } /// Unwrap the value. pub fn into_inner(self) -> T { self.inner } } impl Exclusive { /// Access the value, which requires exclusive access to the wrapper. pub const fn get_mut(&mut self) -> &mut T { &mut self.inner } } impl fmt::Debug for Exclusive { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Exclusive").finish_non_exhaustive() } } #[cfg(test)] #[commonware_macros::test_group("miri")] mod tests { use super::Exclusive; use std::cell::Cell; #[test] fn test_exclusive_is_sync_and_grants_exclusive_access() { fn assert_sync(_: &T) {} // Cell is Send but not Sync; the wrapper is both, so it can be shared across threads. let mut exclusive = Exclusive::new(Cell::new(1u32)); assert_sync(&exclusive); std::thread::scope(|scope| { let shared = &exclusive; scope.spawn(move || { assert_eq!(format!("{shared:?}"), "Exclusive { .. }"); }); }); exclusive.get_mut().set(2); assert_eq!(exclusive.into_inner().into_inner(), 2); } }