@@ -106,6 +106,14 @@ pub struct Notify {
106
106
waiters : Mutex < WaitList > ,
107
107
}
108
108
109
+ #[ derive( Debug , Clone , Copy ) ]
110
+ enum NotificationType {
111
+ // Notification triggered by calling `notify_waiters`
112
+ AllWaiters ,
113
+ // Notification triggered by calling `notify_one`
114
+ OneWaiter ,
115
+ }
116
+
109
117
#[ derive( Debug ) ]
110
118
struct Waiter {
111
119
/// Intrusive linked-list pointers
@@ -115,7 +123,7 @@ struct Waiter {
115
123
waker : Option < Waker > ,
116
124
117
125
/// `true` if the notification has been assigned to this waiter.
118
- notified : bool ,
126
+ notified : Option < NotificationType > ,
119
127
120
128
/// Should not be `Unpin`.
121
129
_p : PhantomPinned ,
@@ -230,7 +238,7 @@ impl Notify {
230
238
waiter : UnsafeCell :: new ( Waiter {
231
239
pointers : linked_list:: Pointers :: new ( ) ,
232
240
waker : None ,
233
- notified : false ,
241
+ notified : None ,
234
242
_p : PhantomPinned ,
235
243
} ) ,
236
244
}
@@ -327,9 +335,9 @@ impl Notify {
327
335
// Safety: `waiters` lock is still held.
328
336
let waiter = unsafe { waiter. as_mut ( ) } ;
329
337
330
- assert ! ( ! waiter. notified) ;
338
+ assert ! ( waiter. notified. is_none ( ) ) ;
331
339
332
- waiter. notified = true ;
340
+ waiter. notified = Some ( NotificationType :: AllWaiters ) ;
333
341
334
342
if let Some ( waker) = waiter. waker . take ( ) {
335
343
waker. wake ( ) ;
@@ -375,9 +383,9 @@ fn notify_locked(waiters: &mut WaitList, state: &AtomicU8, curr: u8) -> Option<W
375
383
// Safety: `waiters` lock is still held.
376
384
let waiter = unsafe { waiter. as_mut ( ) } ;
377
385
378
- assert ! ( ! waiter. notified) ;
386
+ assert ! ( waiter. notified. is_none ( ) ) ;
379
387
380
- waiter. notified = true ;
388
+ waiter. notified = Some ( NotificationType :: OneWaiter ) ;
381
389
let waker = waiter. waker . take ( ) ;
382
390
383
391
if waiters. is_empty ( ) {
@@ -506,11 +514,11 @@ impl Future for Notified<'_> {
506
514
// Safety: called while locked
507
515
let w = unsafe { & mut * waiter. get ( ) } ;
508
516
509
- if w. notified {
517
+ if w. notified . is_some ( ) {
510
518
// Our waker has been notified. Reset the fields and
511
519
// remove it from the list.
512
520
w. waker = None ;
513
- w. notified = false ;
521
+ w. notified = None ;
514
522
515
523
* state = Done ;
516
524
} else {
@@ -582,14 +590,13 @@ impl Drop for Notified<'_> {
582
590
notify. state . store ( EMPTY , SeqCst ) ;
583
591
}
584
592
585
- // See if the node was notified but not received. In this case, the
586
- // notification must be sent to another waiter.
593
+ // See if the node was notified but not received. In this case, if
594
+ // the notification was triggered via `notify_one`, it must be sent
595
+ // to the next waiter.
587
596
//
588
597
// Safety: with the entry removed from the linked list, there can be
589
598
// no concurrent access to the entry
590
- let notified = unsafe { ( * waiter. get ( ) ) . notified } ;
591
-
592
- if notified {
599
+ if let Some ( NotificationType :: OneWaiter ) = unsafe { ( * waiter. get ( ) ) . notified } {
593
600
if let Some ( waker) = notify_locked ( & mut waiters, & notify. state , notify_state) {
594
601
drop ( waiters) ;
595
602
waker. wake ( ) ;
0 commit comments