1
1
//! Defines [`Exclusive`].
2
2
3
+ use core:: cmp:: Ordering ;
3
4
use core:: fmt;
4
5
use core:: future:: Future ;
5
- use core:: marker:: Tuple ;
6
+ use core:: hash:: { Hash , Hasher } ;
7
+ use core:: marker:: { StructuralPartialEq , Tuple } ;
6
8
use core:: ops:: { Coroutine , CoroutineState } ;
7
9
use core:: pin:: Pin ;
8
10
use core:: task:: { Context , Poll } ;
9
11
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.
12
+ /// `Exclusive` provides _mutable_ access, also referred to as _exclusive_
13
+ /// access to the underlying value. However, it only permits _immutable_, or _shared_
14
+ /// access to the underlying value when that value is [`Sync`] .
13
15
///
14
16
/// 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`
17
+ /// implement `Sync`. Indeed, the safety requirements of `Sync` state that for `Exclusive`
16
18
/// 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
+ /// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive<T>` for non-`Sync` T
20
+ /// has no API whatsoever, making it useless, thus harmless, thus memory safe.
19
21
///
20
22
/// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
21
23
/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
22
24
/// Rust compiler that something is `Sync` in practice.
23
25
///
24
26
/// ## Examples
25
- /// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
27
+ ///
28
+ /// Using a non-`Sync` future prevents the wrapping struct from being `Sync`:
29
+ ///
26
30
/// ```compile_fail
27
31
/// use core::cell::Cell;
28
32
///
@@ -43,7 +47,8 @@ use core::task::{Context, Poll};
43
47
/// ```
44
48
///
45
49
/// `Exclusive` ensures the struct is `Sync` without stripping the future of its
46
- /// functionality.
50
+ /// functionality:
51
+ ///
47
52
/// ```
48
53
/// #![feature(exclusive_wrapper)]
49
54
/// use core::cell::Cell;
@@ -66,6 +71,7 @@ use core::task::{Context, Poll};
66
71
/// ```
67
72
///
68
73
/// ## Parallels with a mutex
74
+ ///
69
75
/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of
70
76
/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
71
77
/// for any value. This is a parallel with the fact that
@@ -75,7 +81,7 @@ use core::task::{Context, Poll};
75
81
#[ doc( alias = "SyncWrapper" ) ]
76
82
#[ doc( alias = "SyncCell" ) ]
77
83
#[ doc( alias = "Unique" ) ]
78
- // `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would
84
+ // `Exclusive` can't have derived `PartialOrd`, `Clone`, etc. impls as they would
79
85
// use `&` access to the inner value, violating the `Sync` impl's safety
80
86
// requirements.
81
87
#[ derive( Default ) ]
@@ -195,6 +201,17 @@ where
195
201
}
196
202
}
197
203
204
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
205
+ impl < F , Args > Fn < Args > for Exclusive < F >
206
+ where
207
+ F : Sync + Fn < Args > ,
208
+ Args : Tuple ,
209
+ {
210
+ extern "rust-call" fn call ( & self , args : Args ) -> Self :: Output {
211
+ self . as_ref ( ) . call ( args)
212
+ }
213
+ }
214
+
198
215
#[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
199
216
impl < T > Future for Exclusive < T >
200
217
where
@@ -221,3 +238,80 @@ where
221
238
G :: resume ( self . get_pin_mut ( ) , arg)
222
239
}
223
240
}
241
+
242
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
243
+ impl < T > AsRef < T > for Exclusive < T >
244
+ where
245
+ T : Sync + ?Sized ,
246
+ {
247
+ #[ inline]
248
+ fn as_ref ( & self ) -> & T {
249
+ & self . inner
250
+ }
251
+ }
252
+
253
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
254
+ impl < T > Clone for Exclusive < T >
255
+ where
256
+ T : Sync + Clone ,
257
+ {
258
+ #[ inline]
259
+ fn clone ( & self ) -> Self {
260
+ Self { inner : self . inner . clone ( ) }
261
+ }
262
+ }
263
+
264
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
265
+ impl < T > Copy for Exclusive < T > where T : Sync + Copy { }
266
+
267
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
268
+ impl < T , U > PartialEq < Exclusive < U > > for Exclusive < T >
269
+ where
270
+ T : Sync + PartialEq < U > + ?Sized ,
271
+ U : Sync + ?Sized ,
272
+ {
273
+ #[ inline]
274
+ fn eq ( & self , other : & Exclusive < U > ) -> bool {
275
+ self . inner == other. inner
276
+ }
277
+ }
278
+
279
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
280
+ impl < T > StructuralPartialEq for Exclusive < T > where T : Sync + StructuralPartialEq + ?Sized { }
281
+
282
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
283
+ impl < T > Eq for Exclusive < T > where T : Sync + Eq + ?Sized { }
284
+
285
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
286
+ impl < T > Hash for Exclusive < T >
287
+ where
288
+ T : Sync + Hash + ?Sized ,
289
+ {
290
+ #[ inline]
291
+ fn hash < H : Hasher > ( & self , state : & mut H ) {
292
+ Hash :: hash ( & self . inner , state)
293
+ }
294
+ }
295
+
296
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
297
+ impl < T , U > PartialOrd < Exclusive < U > > for Exclusive < T >
298
+ where
299
+ T : Sync + PartialOrd < U > + ?Sized ,
300
+ U : Sync + ?Sized ,
301
+ {
302
+ #[ inline]
303
+ fn partial_cmp ( & self , other : & Exclusive < U > ) -> Option < Ordering > {
304
+ self . inner . partial_cmp ( & other. inner )
305
+ }
306
+ }
307
+
308
+ #[ unstable( feature = "exclusive_wrapper" , issue = "98407" ) ]
309
+ impl < T > Ord for Exclusive < T >
310
+ where
311
+ T : Sync + Ord + ?Sized ,
312
+ {
313
+ #[ inline]
314
+ fn cmp ( & self , other : & Self ) -> Ordering {
315
+ self . inner . cmp ( & other. inner )
316
+ }
317
+ }
0 commit comments