Struct Exclusive
struct Exclusive<T: ?Sized> { ... }
Exclusive provides mutable access, also referred to as exclusive
access to the underlying value. However, it only permits immutable, or shared
access to the underlying value when that value is Sync.
While this may seem not very useful, it allows Exclusive to unconditionally
implement Sync. Indeed, the safety requirements of Sync state that for Exclusive
to be Sync, it must be sound to share across threads, that is, it must be sound
for &Exclusive to cross thread boundaries. By design, a &Exclusive<T> for non-Sync T
has no API whatsoever, making it useless, thus harmless, thus memory safe.
Certain constructs like Futures can only be used with exclusive access,
and are often Send but not Sync, so Exclusive can be used as hint to the
Rust compiler that something is Sync in practice.
Examples
Using a non-Sync future prevents the wrapping struct from being Sync:
use core::cell::Cell;
async fn other() {}
fn assert_sync<T: Sync>(t: T) {}
struct State<F> {
future: F
}
assert_sync(State {
future: async {
let cell = Cell::new(1);
let cell_ref = &cell;
other().await;
let value = cell_ref.get();
}
});
Exclusive ensures the struct is Sync without stripping the future of its
functionality:
use Cell;
use Exclusive;
async
assert_sync;
Parallels with a mutex
In some sense, Exclusive can be thought of as a compile-time version of
a mutex, as the borrow-checker guarantees that only one &mut can exist
for any value. This is a parallel with the fact that
& and &mut references together can be thought of as a compile-time
version of a read-write lock.
Implementations
impl<T: ?Sized> Exclusive<T>
const fn get_mut(self: &mut Self) -> &mut TGets exclusive access to the underlying value.
const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>Gets pinned exclusive access to the underlying value.
Exclusiveis considered to structurally pin the underlying value, which means unpinnedExclusives can produce unpinned access to the underlying value, but pinnedExclusives only produce pinned access to the underlying value.const fn from_mut(r: &mut T) -> &mut Exclusive<T>Build a mutable reference to an
Exclusive<T>from a mutable reference to aT. This allows you to skip building anExclusivewithExclusive::new.const fn from_pin_mut(r: Pin<&mut T>) -> Pin<&mut Exclusive<T>>Build a pinned mutable reference to an
Exclusive<T>from a pinned mutable reference to aT. This allows you to skip building anExclusivewithExclusive::new.
impl<T: Sized> Exclusive<T>
const fn new(t: T) -> SelfWrap a value in an
Exclusiveconst fn into_inner(self: Self) -> TUnwrap the value contained in the
Exclusive
impl<F> IntoFuture for Exclusive<T>
fn into_future(self: Self) -> <F as IntoFuture>::IntoFuture
impl<F> Pattern for Exclusive<T>
fn into_searcher<'a>(self: Self, haystack: &'a str) -> CharPredicateSearcher<'a, F>fn is_contained_in<'a>(self: Self, haystack: &'a str) -> boolfn is_prefix_of<'a>(self: Self, haystack: &'a str) -> boolfn strip_prefix_of<'a>(self: Self, haystack: &'a str) -> Option<&'a str>fn is_suffix_of<'a>(self: Self, haystack: &'a str) -> bool where CharPredicateSearcher<'a, F>: ReverseSearcher<'a>fn strip_suffix_of<'a>(self: Self, haystack: &'a str) -> Option<&'a str> where CharPredicateSearcher<'a, F>: ReverseSearcher<'a>
impl<F, Args> Fn for Exclusive<F>
extern Other("\"rust-call\"") fn call(self: &Self, args: Args) -> <Self as >::Output
impl<F, Args> FnMut for Exclusive<F>
extern Other("\"rust-call\"") fn call_mut(self: &mut Self, args: Args) -> <Self as >::Output
impl<F, Args> FnOnce for Exclusive<F>
extern Other("\"rust-call\"") fn call_once(self: Self, args: Args) -> <Self as >::Output
impl<R, G> Coroutine for Exclusive<G>
fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<<Self as >::Yield, <Self as >::Return>
impl<T> Any for Exclusive<T>
fn type_id(self: &Self) -> TypeId
impl<T> AsRef for Exclusive<T>
fn as_ref(self: &Self) -> &T
impl<T> Borrow for Exclusive<T>
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for Exclusive<T>
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> Clone for Exclusive<T>
fn clone(self: &Self) -> Self
impl<T> CloneToUninit for Exclusive<T>
unsafe fn clone_to_uninit(self: &Self, dest: *mut u8)
impl<T> Copy for Exclusive<T>
impl<T> Eq for Exclusive<T>
impl<T> Freeze for Exclusive<T>
impl<T> From for Exclusive<T>
fn from(t: T) -> Self
impl<T> From for Exclusive<T>
fn from(t: T) -> TReturns the argument unchanged.
impl<T> From for Exclusive<T>
fn from(t: never) -> T
impl<T> Future for Exclusive<T>
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<<Self as >::Output>
impl<T> Hash for Exclusive<T>
fn hash<H: Hasher>(self: &Self, state: &mut H)
impl<T> Ord for Exclusive<T>
fn cmp(self: &Self, other: &Self) -> Ordering
impl<T> RefUnwindSafe for Exclusive<T>
impl<T> Send for Exclusive<T>
impl<T> StructuralPartialEq for Exclusive<T>
impl<T> Unpin for Exclusive<T>
impl<T> UnsafeUnpin for Exclusive<T>
impl<T> UnwindSafe for Exclusive<T>
impl<T, U> Into for Exclusive<T>
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> PartialEq for Exclusive<T>
fn eq(self: &Self, other: &Exclusive<U>) -> bool
impl<T, U> PartialOrd for Exclusive<T>
fn partial_cmp(self: &Self, other: &Exclusive<U>) -> Option<Ordering>
impl<T, U> TryFrom for Exclusive<T>
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for Exclusive<T>
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>
impl<T: $crate::default::Default + ?Sized> Default for Exclusive<T>
fn default() -> Exclusive<T>
impl<T: ?Sized> Debug for Exclusive<T>
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result<(), Error>