1 | //! Defines [`Exclusive`]. |
2 | |
3 | use core::fmt; |
4 | use core::future::Future; |
5 | use core::marker::Tuple; |
6 | use core::ops::{Coroutine, CoroutineState}; |
7 | use core::pin::Pin; |
8 | use core::task::{Context, Poll}; |
9 | |
10 | /// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_ |
11 | /// access to the underlying value. It provides no _immutable_, or _shared_ |
12 | /// access to the underlying value. |
13 | /// |
14 | /// While this may seem not very useful, it allows `Exclusive` to _unconditionally_ |
15 | /// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive` |
16 | /// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound |
17 | /// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API |
18 | /// whatsoever, making it useless, thus harmless, thus memory safe. |
19 | /// |
20 | /// Certain constructs like [`Future`]s can only be used with _exclusive_ access, |
21 | /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the |
22 | /// Rust compiler that something is `Sync` in practice. |
23 | /// |
24 | /// ## Examples |
25 | /// Using a non-`Sync` future prevents the wrapping struct from being `Sync` |
26 | /// ```compile_fail |
27 | /// use core::cell::Cell; |
28 | /// |
29 | /// async fn other() {} |
30 | /// fn assert_sync<T: Sync>(t: T) {} |
31 | /// struct State<F> { |
32 | /// future: F |
33 | /// } |
34 | /// |
35 | /// assert_sync(State { |
36 | /// future: async { |
37 | /// let cell = Cell::new(1); |
38 | /// let cell_ref = &cell; |
39 | /// other().await; |
40 | /// let value = cell_ref.get(); |
41 | /// } |
42 | /// }); |
43 | /// ``` |
44 | /// |
45 | /// `Exclusive` ensures the struct is `Sync` without stripping the future of its |
46 | /// functionality. |
47 | /// ``` |
48 | /// #![feature(exclusive_wrapper)] |
49 | /// use core::cell::Cell; |
50 | /// use core::sync::Exclusive; |
51 | /// |
52 | /// async fn other() {} |
53 | /// fn assert_sync<T: Sync>(t: T) {} |
54 | /// struct State<F> { |
55 | /// future: Exclusive<F> |
56 | /// } |
57 | /// |
58 | /// assert_sync(State { |
59 | /// future: Exclusive::new(async { |
60 | /// let cell = Cell::new(1); |
61 | /// let cell_ref = &cell; |
62 | /// other().await; |
63 | /// let value = cell_ref.get(); |
64 | /// }) |
65 | /// }); |
66 | /// ``` |
67 | /// |
68 | /// ## Parallels with a mutex |
69 | /// In some sense, `Exclusive` can be thought of as a _compile-time_ version of |
70 | /// a mutex, as the borrow-checker guarantees that only one `&mut` can exist |
71 | /// for any value. This is a parallel with the fact that |
72 | /// `&` and `&mut` references together can be thought of as a _compile-time_ |
73 | /// version of a read-write lock. |
74 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
75 | #[doc (alias = "SyncWrapper" )] |
76 | #[doc (alias = "SyncCell" )] |
77 | #[doc (alias = "Unique" )] |
78 | // `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would |
79 | // use `&` access to the inner value, violating the `Sync` impl's safety |
80 | // requirements. |
81 | #[derive (Default)] |
82 | #[repr (transparent)] |
83 | pub struct Exclusive<T: ?Sized> { |
84 | inner: T, |
85 | } |
86 | |
87 | // See `Exclusive`'s docs for justification. |
88 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
89 | unsafe impl<T: ?Sized> Sync for Exclusive<T> {} |
90 | |
91 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
92 | impl<T: ?Sized> fmt::Debug for Exclusive<T> { |
93 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { |
94 | f.debug_struct(name:"Exclusive" ).finish_non_exhaustive() |
95 | } |
96 | } |
97 | |
98 | impl<T: Sized> Exclusive<T> { |
99 | /// Wrap a value in an `Exclusive` |
100 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
101 | #[must_use ] |
102 | #[inline ] |
103 | pub const fn new(t: T) -> Self { |
104 | Self { inner: t } |
105 | } |
106 | |
107 | /// Unwrap the value contained in the `Exclusive` |
108 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
109 | #[must_use ] |
110 | #[inline ] |
111 | pub const fn into_inner(self) -> T { |
112 | self.inner |
113 | } |
114 | } |
115 | |
116 | impl<T: ?Sized> Exclusive<T> { |
117 | /// Get exclusive access to the underlying value. |
118 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
119 | #[must_use ] |
120 | #[inline ] |
121 | pub const fn get_mut(&mut self) -> &mut T { |
122 | &mut self.inner |
123 | } |
124 | |
125 | /// Get pinned exclusive access to the underlying value. |
126 | /// |
127 | /// `Exclusive` is considered to _structurally pin_ the underlying |
128 | /// value, which means _unpinned_ `Exclusive`s can produce _unpinned_ |
129 | /// access to the underlying value, but _pinned_ `Exclusive`s only |
130 | /// produce _pinned_ access to the underlying value. |
131 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
132 | #[must_use ] |
133 | #[inline ] |
134 | pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { |
135 | // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned |
136 | // `Pin::map_unchecked_mut` is not const, so we do this conversion manually |
137 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } |
138 | } |
139 | |
140 | /// Build a _mutable_ reference to an `Exclusive<T>` from |
141 | /// a _mutable_ reference to a `T`. This allows you to skip |
142 | /// building an `Exclusive` with [`Exclusive::new`]. |
143 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
144 | #[must_use ] |
145 | #[inline ] |
146 | pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> { |
147 | // SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic |
148 | unsafe { &mut *(r as *mut T as *mut Exclusive<T>) } |
149 | } |
150 | |
151 | /// Build a _pinned mutable_ reference to an `Exclusive<T>` from |
152 | /// a _pinned mutable_ reference to a `T`. This allows you to skip |
153 | /// building an `Exclusive` with [`Exclusive::new`]. |
154 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
155 | #[must_use ] |
156 | #[inline ] |
157 | pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> { |
158 | // SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned |
159 | // `Pin::map_unchecked_mut` is not const, so we do this conversion manually |
160 | unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) } |
161 | } |
162 | } |
163 | |
164 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
165 | impl<T> From<T> for Exclusive<T> { |
166 | #[inline ] |
167 | fn from(t: T) -> Self { |
168 | Self::new(t) |
169 | } |
170 | } |
171 | |
172 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
173 | impl<F, Args> FnOnce<Args> for Exclusive<F> |
174 | where |
175 | F: FnOnce<Args>, |
176 | Args: Tuple, |
177 | { |
178 | type Output = F::Output; |
179 | |
180 | extern "rust-call" fn call_once(self, args: Args) -> Self::Output { |
181 | self.into_inner().call_once(args) |
182 | } |
183 | } |
184 | |
185 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
186 | impl<F, Args> FnMut<Args> for Exclusive<F> |
187 | where |
188 | F: FnMut<Args>, |
189 | Args: Tuple, |
190 | { |
191 | extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output { |
192 | self.get_mut().call_mut(args) |
193 | } |
194 | } |
195 | |
196 | #[unstable (feature = "exclusive_wrapper" , issue = "98407" )] |
197 | impl<T> Future for Exclusive<T> |
198 | where |
199 | T: Future + ?Sized, |
200 | { |
201 | type Output = T::Output; |
202 | |
203 | #[inline ] |
204 | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
205 | self.get_pin_mut().poll(cx) |
206 | } |
207 | } |
208 | |
209 | #[unstable (feature = "coroutine_trait" , issue = "43122" )] // also #98407 |
210 | impl<R, G> Coroutine<R> for Exclusive<G> |
211 | where |
212 | G: Coroutine<R> + ?Sized, |
213 | { |
214 | type Yield = G::Yield; |
215 | type Return = G::Return; |
216 | |
217 | #[inline ] |
218 | fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState<Self::Yield, Self::Return> { |
219 | G::resume(self.get_pin_mut(), arg) |
220 | } |
221 | } |
222 | |