Struct SyncView
#[repr(transparent)]
pub struct SyncView<T: ?Sized> { pub(in ::sync::sync_view) inner: T }
SyncView 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 SyncView to unconditionally
implement Sync. Indeed, the safety requirements of Sync state that for SyncView
to be Sync, it must be sound to share across threads, that is, it must be sound
for &SyncView to cross thread boundaries. By design, a &SyncView<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 SyncView 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();
}
});
SyncView ensures the struct is Sync without stripping the future of its
functionality:
use Cell;
use SyncView;
async
assert_sync;
Parallels with a mutex
In some sense, SyncView 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.
Fields
inner: T
Implementations
impl<T: ?Sized + Sync> SyncView<T>
const fn as_pin_ref(self: Pin<&Self>) -> Pin<&T>Gets pinned shared access to the underlying value.
SyncViewis considered to structurally pin the underlying value, which means unpinnedSyncViews can produce unpinned access to the underlying value, but pinnedSyncViews only produce pinned access to the underlying value.
impl<T: ?Sized> SyncView<T>
const fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>Gets pinned exclusive access to the underlying value.
SyncViewis considered to structurally pin the underlying value, which means unpinnedSyncViews can produce unpinned access to the underlying value, but pinnedSyncViews only produce pinned access to the underlying value.const fn from_mut(r: &mut T) -> &mut SyncView<T>Build a mutable reference to an
SyncView<T>from a mutable reference to aT. This allows you to skip building anSyncViewwithSyncView::new.const fn from_pin_mut(r: Pin<&mut T>) -> Pin<&mut SyncView<T>>Build a pinned mutable reference to an
SyncView<T>from a pinned mutable reference to aT. This allows you to skip building anSyncViewwithSyncView::new.
impl<T: Sized> SyncView<T>
const fn new(t: T) -> SelfWrap a value in an
SyncViewconst fn into_inner(self) -> TUnwrap the value contained in the
SyncView
Trait Implementations
impl<F, Args> AsyncFn<Args> for SyncView<F>
where
F: Sync + AsyncFn<Args>,
Args: Tuple,
extern ""rust-call"" fn async_call(&self, args: Args) -> Self::CallRefFuture<'_>
impl<F, Args> AsyncFnMut<Args> for SyncView<F>
where
F: AsyncFnMut<Args>,
Args: Tuple,
type CallRefFuture<'a> = <F as AsyncFnMut<Args>>::CallRefFuture<'a>;extern ""rust-call"" fn async_call_mut(&mut self, args: Args) -> Self::CallRefFuture<'_>
impl<F, Args> AsyncFnOnce<Args> for SyncView<F>
where
F: AsyncFnOnce<Args>,
Args: Tuple,
type CallOnceFuture = <F as AsyncFnOnce<Args>>::CallOnceFuture;type Output = <F as AsyncFnOnce<Args>>::Output;extern ""rust-call"" fn async_call_once(self, args: Args) -> Self::CallOnceFuture
impl<F, Args> Fn<Args> for SyncView<F>
where
F: Sync + ~const Fn<Args>,
Args: Tuple,
extern ""rust-call"" fn call(&self, args: Args) -> Self::Output
impl<F, Args> FnMut<Args> for SyncView<F>
where
F: ~const FnMut<Args>,
Args: Tuple,
extern ""rust-call"" fn call_mut(&mut self, args: Args) -> Self::Output
impl<F, Args> FnOnce<Args> for SyncView<F>
where
F: ~const FnOnce<Args>,
Args: Tuple,
type Output = <F as FnOnce<Args>>::Output;extern ""rust-call"" fn call_once(self, args: Args) -> Self::Output
impl<R, G> Coroutine<R> for SyncView<G>
where
G: Coroutine<R> + ?Sized,
type Yield = <G as Coroutine<R>>::Yield;type Return = <G as Coroutine<R>>::Return;fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return>
impl<T> AsMut<T> for SyncView<T>
where
T: ?Sized,
fn as_mut(&mut self) -> &mut TGets exclusive access to the underlying value.
impl<T> AsRef<T> for SyncView<T>
where
T: Sync + ?Sized,
fn as_ref(&self) -> &TGets shared access to the underlying value.
impl<T> Clone for SyncView<T>
where
T: Sync + ~const Clone,
fn clone(&self) -> Self
impl<T> Copy for SyncView<T>
where
T: Sync + Copy,
impl<T> Default for SyncView<T>
where
T: ~const Default,
fn default() -> Self
impl<T> Eq for SyncView<T>
where
T: Sync + ~const Eq + ?Sized,
impl<T> From<T> for SyncView<T>
fn from(t: T) -> Self
impl<T> Future for SyncView<T>
where
T: Future + ?Sized,
type Output = <T as Future>::Output;fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
impl<T> Hash for SyncView<T>
where
T: Sync + Hash + ?Sized,
fn hash<H: Hasher>(&self, state: &mut H)
impl<T> Ord for SyncView<T>
where
T: Sync + ~const Ord + ?Sized,
fn cmp(&self, other: &Self) -> Ordering
impl<T> StructuralPartialEq for SyncView<T>
where
T: Sync + StructuralPartialEq + ?Sized,
impl<T> TrivialClone for SyncView<T>
where
T: Sync + ~const TrivialClone,
impl<T, U> PartialEq<SyncView<U>> for SyncView<T>
where
T: Sync + ~const PartialEq<U> + ?Sized,
U: Sync + ?Sized,
fn eq(&self, other: &SyncView<U>) -> bool
impl<T, U> PartialOrd<SyncView<U>> for SyncView<T>
where
T: Sync + ~const PartialOrd<U> + ?Sized,
U: Sync + ?Sized,
fn partial_cmp(&self, other: &SyncView<U>) -> Option<Ordering>
impl<T: ?Sized> Debug for SyncView<T>
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>
impl<T: ?Sized> Sync for SyncView<T>
Auto Trait Implementations
impl<T> Freeze for SyncView<T>
where
T: Freeze + ?Sized,
impl<T> RefUnwindSafe for SyncView<T>
where
T: RefUnwindSafe + ?Sized,
impl<T> Send for SyncView<T>
where
T: Send + ?Sized,
impl<T> Unpin for SyncView<T>
where
T: Unpin + ?Sized,
impl<T> UnsafeUnpin for SyncView<T>
where
T: UnsafeUnpin + ?Sized,
impl<T> UnwindSafe for SyncView<T>
where
T: UnwindSafe + ?Sized,
Blanket Implementations
impl<F> IntoFuture for SyncView<T>
where
F: Future,
type Output = <F as Future>::Output;type IntoFuture = F;fn into_future(self) -> <F as IntoFuture>::IntoFuture
impl<F> Pattern for SyncView<T>
where
F: FnMut(char) -> bool,
type Searcher<'a> = CharPredicateSearcher<'a, F>;fn into_searcher<'a>(self, haystack: &'a str) -> CharPredicateSearcher<'a, F>fn is_contained_in<'a>(self, haystack: &'a str) -> boolfn is_prefix_of<'a>(self, haystack: &'a str) -> boolfn strip_prefix_of<'a>(self, haystack: &'a str) -> Option<&'a str>fn is_suffix_of<'a>(self, haystack: &'a str) -> bool where CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,fn strip_suffix_of<'a>(self, haystack: &'a str) -> Option<&'a str> where CharPredicateSearcher<'a, F>: ReverseSearcher<'a>,
impl<T> Any for SyncView<T>
where
T: 'static + ?Sized,
fn type_id(&self) -> TypeId
impl<T> Borrow<T> for SyncView<T>
where
T: ?Sized,
fn borrow(&self) -> &T
impl<T> BorrowMut<T> for SyncView<T>
where
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
impl<T> CloneToUninit for SyncView<T>
where
T: Clone,
unsafe fn clone_to_uninit(&self, dest: *mut u8)
impl<T> From<T> for SyncView<T>
fn from(t: T) -> TReturns the argument unchanged.
impl<T> From<never> for SyncView<T>
fn from(t: never) -> T
impl<T> Printable for SyncView<T>
where
T: Copy + Debug,
impl<T> SizeHint for SyncView<T>
where
T: ?Sized,
fn lower_bound(&self) -> usizefn upper_bound(&self) -> Option<usize>
impl<T> SizedTypeProperties for SyncView<T>
impl<T, U> Into<U> for SyncView<T>
where
U: From<T>,
fn into(self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom<U> for SyncView<T>
where
U: Into<T>,
type Error = Infallible;fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto<U> for SyncView<T>
where
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error;fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>