60
60
//! }
61
61
//! ```
62
62
63
- #![ cfg_attr( not( feature = "std" ) , no_std) ]
63
+ #![ cfg_attr( all ( not( feature = "std" ) , not ( test ) ) , no_std) ]
64
64
#![ warn( missing_docs, missing_debug_implementations, rust_2018_idioms) ]
65
65
66
66
extern crate alloc;
@@ -69,7 +69,7 @@ extern crate alloc;
69
69
#[ cfg_attr( not( feature = "std" ) , path = "no_std.rs" ) ]
70
70
mod sys;
71
71
72
- use alloc:: sync :: Arc ;
72
+ use alloc:: boxed :: Box ;
73
73
74
74
use core:: borrow:: Borrow ;
75
75
use core:: fmt;
@@ -79,15 +79,23 @@ use core::mem::ManuallyDrop;
79
79
use core:: pin:: Pin ;
80
80
use core:: ptr;
81
81
use core:: task:: { Context , Poll , Waker } ;
82
- use core:: usize;
83
82
84
- use sync:: atomic:: { self , AtomicPtr , AtomicUsize , Ordering } ;
85
-
86
- #[ cfg( feature = "std" ) ]
87
- use std:: panic:: { RefUnwindSafe , UnwindSafe } ;
88
83
#[ cfg( feature = "std" ) ]
89
84
use std:: time:: { Duration , Instant } ;
90
85
86
+ use sync:: atomic:: { AtomicPtr , AtomicUsize , Ordering } ;
87
+ use sync:: { Arc , WithMut } ;
88
+
89
+ /// 1.39-compatible replacement for `matches!`
90
+ macro_rules! matches {
91
+ ( $expr: expr, $( $pattern: pat) |+ $( if $guard: expr) ?) => {
92
+ match $expr {
93
+ $( $pattern) |+ $( if $guard) ? => true ,
94
+ _ => false ,
95
+ }
96
+ } ;
97
+ }
98
+
91
99
/// Inner state of [`Event`].
92
100
struct Inner {
93
101
/// The number of notified entries, or `usize::MAX` if all of them have been notified.
@@ -96,11 +104,14 @@ struct Inner {
96
104
notified : AtomicUsize ,
97
105
98
106
/// Inner queue of event listeners.
107
+ ///
108
+ /// On `std` platforms, this is an intrusive linked list. On `no_std` platforms, this is a
109
+ /// more traditional `Vec` of listeners, with an atomic queue used as a backup for high
110
+ /// contention.
99
111
list : sys:: List ,
100
112
}
101
113
102
114
impl Inner {
103
- /// Create a new `Inner`.
104
115
fn new ( ) -> Self {
105
116
Self {
106
117
notified : AtomicUsize :: new ( core:: usize:: MAX ) ,
@@ -137,10 +148,26 @@ pub struct Event {
137
148
inner : AtomicPtr < Inner > ,
138
149
}
139
150
151
+ unsafe impl Send for Event { }
152
+ unsafe impl Sync for Event { }
153
+
140
154
#[ cfg( feature = "std" ) ]
141
- impl UnwindSafe for Event { }
155
+ impl std :: panic :: UnwindSafe for Event { }
142
156
#[ cfg( feature = "std" ) ]
143
- impl RefUnwindSafe for Event { }
157
+ impl std:: panic:: RefUnwindSafe for Event { }
158
+
159
+ impl fmt:: Debug for Event {
160
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
161
+ f. write_str ( "Pad { .. }" )
162
+ }
163
+ }
164
+
165
+ impl Default for Event {
166
+ #[ inline]
167
+ fn default ( ) -> Self {
168
+ Self :: new ( )
169
+ }
170
+ }
144
171
145
172
impl Event {
146
173
/// Creates a new [`Event`].
@@ -153,15 +180,17 @@ impl Event {
153
180
/// let event = Event::new();
154
181
/// ```
155
182
#[ inline]
156
- pub const fn new ( ) -> Event {
157
- Event {
183
+ pub const fn new ( ) -> Self {
184
+ Self {
158
185
inner : AtomicPtr :: new ( ptr:: null_mut ( ) ) ,
159
186
}
160
187
}
161
188
162
189
/// Returns a guard listening for a notification.
163
190
///
164
- /// This method emits a `SeqCst` fence after registering a listener.
191
+ /// This method emits a `SeqCst` fence after registering a listener. For now, this method
192
+ /// is an alias for calling [`EventListener::new()`], pinning it to the heap, and then
193
+ /// inserting it into a list.
165
194
///
166
195
/// # Examples
167
196
///
@@ -260,7 +289,7 @@ impl Event {
260
289
// Notify if there is at least one unnotified listener and the number of notified
261
290
// listeners is less than `n`.
262
291
if inner. notified . load ( Ordering :: Acquire ) < n {
263
- inner. notify ( n, false ) ;
292
+ inner. notify ( n, true ) ;
264
293
}
265
294
}
266
295
}
@@ -302,7 +331,7 @@ impl Event {
302
331
303
332
if let Some ( inner) = self . try_inner ( ) {
304
333
// Notify if there is at least one unnotified listener.
305
- if inner. notified . load ( Ordering :: Acquire ) < usize:: MAX {
334
+ if inner. notified . load ( Ordering :: Acquire ) < core :: usize:: MAX {
306
335
inner. notify ( n, true ) ;
307
336
}
308
337
}
@@ -347,34 +376,35 @@ impl Event {
347
376
pub fn notify_additional_relaxed ( & self , n : usize ) {
348
377
if let Some ( inner) = self . try_inner ( ) {
349
378
// Notify if there is at least one unnotified listener.
350
- if inner. notified . load ( Ordering :: Acquire ) < usize:: MAX {
379
+ if inner. notified . load ( Ordering :: Acquire ) < core :: usize:: MAX {
351
380
inner. notify ( n, true ) ;
352
381
}
353
382
}
354
383
}
355
384
356
- /// Returns a reference to the inner state if it was initialized.
385
+ /// Return a reference to the inner state if it has been initialized.
357
386
#[ inline]
358
387
fn try_inner ( & self ) -> Option < & Inner > {
359
388
let inner = self . inner . load ( Ordering :: Acquire ) ;
360
389
unsafe { inner. as_ref ( ) }
361
390
}
362
391
363
- /// Returns a raw pointer to the inner state, initializing it if necessary .
392
+ /// Returns a raw, initialized pointer to the inner state.
364
393
///
365
394
/// This returns a raw pointer instead of reference because `from_raw`
366
- /// requires raw/mut provenance: <https://github.com/rust-lang/rust/pull/67339>
395
+ /// requires raw/mut provenance: <https://github.com/rust-lang/rust/pull/67339>.
367
396
fn inner ( & self ) -> * const Inner {
368
397
let mut inner = self . inner . load ( Ordering :: Acquire ) ;
369
398
370
- // Initialize the state if this is its first use.
399
+ // If this is the first use, initialize the state .
371
400
if inner. is_null ( ) {
372
- // Allocate on the heap.
401
+ // Allocate the state on the heap.
373
402
let new = Arc :: new ( Inner :: new ( ) ) ;
374
- // Convert the heap-allocated state into a raw pointer.
403
+
404
+ // Convert the state to a raw pointer.
375
405
let new = Arc :: into_raw ( new) as * mut Inner ;
376
406
377
- // Attempt to replace the null- pointer with the new state pointer.
407
+ // Replace the null pointer with the new state pointer.
378
408
inner = self
379
409
. inner
380
410
. compare_exchange ( inner, new, Ordering :: AcqRel , Ordering :: Acquire )
@@ -400,26 +430,14 @@ impl Event {
400
430
impl Drop for Event {
401
431
#[ inline]
402
432
fn drop ( & mut self ) {
403
- let inner : * mut Inner = * self . inner . get_mut ( ) ;
404
-
405
- // If the state pointer has been initialized, deallocate it.
406
- if !inner . is_null ( ) {
407
- unsafe {
408
- drop ( Arc :: from_raw ( inner ) ) ;
433
+ self . inner . with_mut ( | & mut inner| {
434
+ // If the state pointer has been initialized, drop it.
435
+ if !inner . is_null ( ) {
436
+ unsafe {
437
+ drop ( Arc :: from_raw ( inner ) ) ;
438
+ }
409
439
}
410
- }
411
- }
412
- }
413
-
414
- impl fmt:: Debug for Event {
415
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
416
- f. pad ( "Event { .. }" )
417
- }
418
- }
419
-
420
- impl Default for Event {
421
- fn default ( ) -> Event {
422
- Event :: new ( )
440
+ } )
423
441
}
424
442
}
425
443
@@ -770,40 +788,35 @@ impl<B: Borrow<Inner> + Unpin> Drop for Listener<B> {
770
788
771
789
/// The state of a listener.
772
790
#[ derive( Debug , PartialEq ) ]
773
- pub ( crate ) enum State {
774
- /// It has just been created.
791
+ enum State {
792
+ /// The listener was just created.
775
793
Created ,
776
794
777
- /// It has received a notification.
795
+ /// The listener has received a notification.
778
796
///
779
797
/// The `bool` is `true` if this was an "additional" notification.
780
798
Notified ( bool ) ,
781
799
782
- /// A task is polling it .
800
+ /// A task is waiting for a notification .
783
801
Task ( Task ) ,
784
802
785
803
/// Empty hole used to replace a notified listener.
786
804
NotifiedTaken ,
787
805
}
788
806
789
807
impl State {
790
- /// Returns `true` if this is the `Notified` state.
791
- #[ inline]
792
- pub ( crate ) fn is_notified ( & self ) -> bool {
793
- match self {
794
- State :: Notified ( _) | Self :: NotifiedTaken => true ,
795
- _ => false ,
796
- }
808
+ fn is_notified ( & self ) -> bool {
809
+ matches ! ( self , Self :: Notified ( _) | Self :: NotifiedTaken )
797
810
}
798
811
}
799
812
800
- /// An asynchronous waker or thread unparker that can be used to notify a task or thread .
801
- #[ derive( Debug ) ]
813
+ /// A task that can be woken up .
814
+ #[ derive( Debug , Clone ) ]
802
815
enum Task {
803
- /// A waker that can be used to notify a task .
816
+ /// A waker that wakes up a future .
804
817
Waker ( Waker ) ,
805
818
806
- /// An unparker that can be used to notify a thread.
819
+ /// An unparker that wakes up a thread.
807
820
#[ cfg( feature = "std" ) ]
808
821
Unparker ( parking:: Unparker ) ,
809
822
}
@@ -817,12 +830,11 @@ impl Task {
817
830
}
818
831
}
819
832
820
- /// Notifies the task or thread.
821
833
fn wake ( self ) {
822
834
match self {
823
- Task :: Waker ( waker) => waker. wake ( ) ,
835
+ Self :: Waker ( waker) => waker. wake ( ) ,
824
836
#[ cfg( feature = "std" ) ]
825
- Task :: Unparker ( unparker) => {
837
+ Self :: Unparker ( unparker) => {
826
838
unparker. unpark ( ) ;
827
839
}
828
840
}
@@ -836,7 +848,7 @@ impl PartialEq for Task {
836
848
}
837
849
838
850
/// A reference to a task.
839
- #[ derive( Debug , Clone , Copy ) ]
851
+ #[ derive( Clone , Copy ) ]
840
852
enum TaskRef < ' a > {
841
853
/// A waker that wakes up a future.
842
854
Waker ( & ' a Waker ) ,
@@ -890,23 +902,21 @@ fn full_fence() {
890
902
// The ideal solution here would be to use inline assembly, but we're instead creating a
891
903
// temporary atomic variable and compare-and-exchanging its value. No sane compiler to
892
904
// x86 platforms is going to optimize this away.
893
- atomic:: compiler_fence ( Ordering :: SeqCst ) ;
905
+ sync :: atomic:: compiler_fence ( Ordering :: SeqCst ) ;
894
906
let a = AtomicUsize :: new ( 0 ) ;
895
907
let _ = a. compare_exchange ( 0 , 1 , Ordering :: SeqCst , Ordering :: SeqCst ) ;
896
- atomic:: compiler_fence ( Ordering :: SeqCst ) ;
908
+ sync :: atomic:: compiler_fence ( Ordering :: SeqCst ) ;
897
909
} else {
898
- atomic:: fence ( Ordering :: SeqCst ) ;
910
+ sync :: atomic:: fence ( Ordering :: SeqCst ) ;
899
911
}
900
912
}
901
913
902
914
/// Synchronization primitive implementation.
903
915
mod sync {
916
+ pub ( super ) use alloc:: sync:: Arc ;
904
917
pub ( super ) use core:: cell;
905
918
pub ( super ) use core:: sync:: atomic;
906
919
907
- #[ cfg( not( feature = "std" ) ) ]
908
- pub ( super ) use alloc:: sync:: Arc ;
909
-
910
920
#[ cfg( feature = "std" ) ]
911
921
pub ( super ) use std:: sync:: { Mutex , MutexGuard } ;
912
922
0 commit comments