use std::cell::RefCell; /// A trait for types that are **not** [`Send`] only because they would then allow concurrent access to a type that is not [`Sync`]. /// /// The primary example of such a type is `&T`, with `T: !Sync`. /// /// In the authors' understanding, a type can be `!Send` for two distinct reasons: /// /// 1. Because it contains data that *genuinely* cannot be moved between threads, such as thread-local data. /// 2. Because sending the type would allow concurrent access to a `!Sync` type, which is undefined behavior. /// /// `MostlySend` exists to be used in bounds where you need a type whose data is **not** *attached* to a thread /// because you might access it from a different thread, but where you will never access the type **concurrently** from /// multiple threads. /// /// Like [`Send`], `MostlySend` assumes properties on types that cannot be verified by the compiler, which is why implementing /// this trait is unsafe. /// /// # Safety /// /// Implementers of this trait promises that the following properties hold on the implementing type: /// /// 1. Its data can be accessed from any thread and will be the same regardless of the thread accessing it. /// 2. Any operation that can be performed on the type does not depend on the thread that executes it. /// /// As these properties are subtle and are not generally tracked by the Rust type system, great care should be taken before /// implementing `MostlySend` on a type, especially a foreign type. /// /// - An example of a type that verifies (1) and (2) is [`std::rc::Rc`] (when `T` is `Send` and `Sync`). /// - An example of a type that doesn't verify (1) is thread-local data. /// - An example of a type that doesn't verify (2) is [`std::sync::MutexGuard`]: a lot of mutex implementations require that /// a lock is returned to the operating system on the same thread that initially locked the mutex, failing to uphold this /// invariant will cause Undefined Behavior /// (see last ยง in [the nomicon](https://doc.rust-lang.org/nomicon/send-and-sync.html)). /// /// It is **always safe** to implement this trait on a type that is `Send`, but no placeholder impl is provided due to limitations in /// coherency. Use the [`FullySend`] wrapper in this situation. pub unsafe trait MostlySend {} #[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct FullySend(pub T); // SAFETY: a type **fully** send is always mostly send as well. unsafe impl MostlySend for FullySend where T: Send {} unsafe impl MostlySend for RefCell where T: MostlySend {} unsafe impl MostlySend for Option where T: MostlySend {} impl FullySend { pub fn into(self) -> T { self.0 } } impl From for FullySend { fn from(value: T) -> Self { Self(value) } } #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] struct MostlySendWrapper(T); impl MostlySendWrapper { /// # Safety /// /// - (P1) Users of this type will never access the type concurrently from multiple threads without synchronization unsafe fn new(t: T) -> Self { Self(t) } fn as_ref(&self) -> &T { &self.0 } fn as_mut(&mut self) -> &mut T { &mut self.0 } fn into_inner(self) -> T { self.0 } } /// # Safety /// /// 1. `T` is [`MostlySend`], so by its safety contract it can be accessed by any thread and all of its operations are available /// from any thread. /// 2. (P1) of `MostlySendWrapper::new` forces the user to never access the value from multiple threads concurrently. unsafe impl Send for MostlySendWrapper {} /// A wrapper around [`thread_local::ThreadLocal`] that accepts [`MostlySend`] `T`s. #[derive(Default)] pub struct ThreadLocal { inner: thread_local::ThreadLocal>, // FIXME: this should be necessary //_no_send: PhantomData<*mut ()>, } impl ThreadLocal { pub fn new() -> Self { Self { inner: thread_local::ThreadLocal::new() } } pub fn with_capacity(capacity: usize) -> Self { Self { inner: thread_local::ThreadLocal::with_capacity(capacity) } } pub fn clear(&mut self) { self.inner.clear() } pub fn get(&self) -> Option<&T> { self.inner.get().map(|t| t.as_ref()) } pub fn get_or(&self, create: F) -> &T where F: FnOnce() -> T, { self.inner.get_or(|| unsafe { MostlySendWrapper::new(create()) }).as_ref() } pub fn get_or_try(&self, create: F) -> std::result::Result<&T, E> where F: FnOnce() -> std::result::Result, { self.inner .get_or_try(|| unsafe { Ok(MostlySendWrapper::new(create()?)) }) .map(MostlySendWrapper::as_ref) } pub fn get_or_default(&self) -> &T where T: Default, { self.inner.get_or_default().as_ref() } pub fn iter_mut(&mut self) -> IterMut { IterMut(self.inner.iter_mut()) } } impl IntoIterator for ThreadLocal { type Item = T; type IntoIter = IntoIter; fn into_iter(self) -> Self::IntoIter { IntoIter(self.inner.into_iter()) } } pub struct IterMut<'a, T: MostlySend>(thread_local::IterMut<'a, MostlySendWrapper>); impl<'a, T: MostlySend> Iterator for IterMut<'a, T> { type Item = &'a mut T; fn next(&mut self) -> Option { self.0.next().map(|t| t.as_mut()) } } pub struct IntoIter(thread_local::IntoIter>); impl Iterator for IntoIter { type Item = T; fn next(&mut self) -> Option { self.0.next().map(|t| t.into_inner()) } }