| 1 | //! This module contains a type that can make `Send + !Sync` types `Sync` by |
| 2 | //! disallowing all immutable access to the value. |
| 3 | //! |
| 4 | //! A similar primitive is provided in the `sync_wrapper` crate. |
| 5 | |
| 6 | use std::any::Any; |
| 7 | |
| 8 | pub(crate) struct SyncWrapper<T> { |
| 9 | value: T, |
| 10 | } |
| 11 | |
| 12 | // safety: The SyncWrapper being send allows you to send the inner value across |
| 13 | // thread boundaries. |
| 14 | unsafe impl<T: Send> Send for SyncWrapper<T> {} |
| 15 | |
| 16 | // safety: An immutable reference to a SyncWrapper is useless, so moving such an |
| 17 | // immutable reference across threads is safe. |
| 18 | unsafe impl<T> Sync for SyncWrapper<T> {} |
| 19 | |
| 20 | impl<T> SyncWrapper<T> { |
| 21 | pub(crate) fn new(value: T) -> Self { |
| 22 | Self { value } |
| 23 | } |
| 24 | |
| 25 | pub(crate) fn into_inner(self) -> T { |
| 26 | self.value |
| 27 | } |
| 28 | } |
| 29 | |
| 30 | impl SyncWrapper<Box<dyn Any + Send>> { |
| 31 | /// Attempt to downcast using `Any::downcast_ref()` to a type that is known to be `Sync`. |
| 32 | pub(crate) fn downcast_ref_sync<T: Any + Sync>(&self) -> Option<&T> { |
| 33 | // SAFETY: if the downcast fails, the inner value is not touched, |
| 34 | // so no thread-safety violation can occur. |
| 35 | self.value.downcast_ref() |
| 36 | } |
| 37 | } |
| 38 | |