pub struct SyncWrapper<T>(/* private fields */);
Expand description
A mutual exclusion primitive that relies on static type information only
In some cases synchronization can be proven statically: whenever you hold an exclusive &mut
reference, the Rust type system ensures that no other part of the program can hold another
reference to the data. Therefore it is safe to access it even if the current thread obtained
this reference via a channel. Whenever this is the case, the overhead of allocating and locking
a Mutex
can be avoided by using this static version.
One example where this is often applicable is Future
, which requires an exclusive reference
for its poll
method: While a given Future
implementation may not be safe to access by
multiple threads concurrently, the executor can only run the Future
on one thread at any
given time, making it Sync
in practice as long as the implementation is Send
. You can
therefore use the static mutex to prove that your data structure is Sync
even though it
contains such a Future
.
§Example
use sync_wrapper::SyncWrapper;
use std::future::Future;
struct MyThing {
future: SyncWrapper<Box<dyn Future<Output = String> + Send>>,
}
impl MyThing {
// all accesses to `self.future` now require an exclusive reference or ownership
}
fn assert_sync<T: Sync>() {}
assert_sync::<MyThing>();
Implementations§
source§impl<T> SyncWrapper<T>
impl<T> SyncWrapper<T>
sourcepub const fn new(value: T) -> Self
pub const fn new(value: T) -> Self
Creates a new static mutex containing the given value.
§Examples
use sync_wrapper::SyncWrapper;
let mutex = SyncWrapper::new(42);
sourcepub fn get_mut(&mut self) -> &mut T
pub fn get_mut(&mut self) -> &mut T
Acquires a reference to the protected value.
This is safe because it requires an exclusive reference to the mutex. Therefore this method
neither panics nor does it return an error. This is in contrast to Mutex::get_mut
which
returns an error if another thread panicked while holding the lock. It is not recommended
to send an exclusive reference to a potentially damaged value to another thread for further
processing.
§Examples
use sync_wrapper::SyncWrapper;
let mut mutex = SyncWrapper::new(42);
let value = mutex.get_mut();
*value = 0;
assert_eq!(*mutex.get_mut(), 0);
sourcepub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>
pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>
Acquires a pinned reference to the protected value.
See Self::get_mut
for why this method is safe.
§Examples
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
use pin_project_lite::pin_project;
use sync_wrapper::SyncWrapper;
pin_project! {
struct FutureWrapper<F> {
#[pin]
inner: SyncWrapper<F>,
}
}
impl<F: Future> Future for FutureWrapper<F> {
type Output = F::Output;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.project().inner.get_pin_mut().poll(cx)
}
}
sourcepub fn into_inner(self) -> T
pub fn into_inner(self) -> T
Consumes this mutex, returning the underlying data.
This is safe because it requires ownership of the mutex, therefore this method will neither
panic nor does it return an error. This is in contrast to Mutex::into_inner
which
returns an error if another thread panicked while holding the lock. It is not recommended
to send an exclusive reference to a potentially damaged value to another thread for further
processing.
§Examples
use sync_wrapper::SyncWrapper;
let mut mutex = SyncWrapper::new(42);
assert_eq!(mutex.into_inner(), 42);