@@ -49,19 +49,26 @@ impl Parker {
4949 return ;
5050 }
5151
52- loop {
53- // Wait for something to happen.
54- if c :: WaitOnAddress :: is_available ( ) {
52+ if c :: WaitOnAddress :: is_available ( ) {
53+ loop {
54+ // Wait for something to happen, assuming it's still set to PARKED.
5555 c:: WaitOnAddress ( self . ptr ( ) , & PARKED as * const _ as c:: LPVOID , 1 , c:: INFINITE ) ;
56- } else {
57- c:: NtWaitForKeyedEvent ( keyed_event_handle ( ) , self . ptr ( ) , 0 , ptr:: null_mut ( ) ) ;
58- }
59- // Change NOTIFIED=>EMPTY and return in that case.
60- if self . state . compare_and_swap ( NOTIFIED , EMPTY , Acquire ) == NOTIFIED {
61- return ;
62- } else {
63- // Spurious wake up. We loop to try again.
56+ // Change NOTIFIED=>EMPTY but leave PARKED alone.
57+ if self . state . compare_and_swap ( NOTIFIED , EMPTY , Acquire ) == NOTIFIED {
58+ // Actually woken up by unpark().
59+ return ;
60+ } else {
61+ // Spurious wake up. We loop to try again.
62+ }
6463 }
64+ } else {
65+ // Wait for unpark() to produce this event.
66+ c:: NtWaitForKeyedEvent ( keyed_event_handle ( ) , self . ptr ( ) , 0 , ptr:: null_mut ( ) ) ;
67+ // Set the state back to EMPTY (from either PARKED or NOTIFIED).
68+ // Note that we don't just write EMPTY, but use swap() to also
69+ // include a acquire-ordered read to synchronize with unpark()'s
70+ // release-ordered write.
71+ self . state . swap ( EMPTY , Acquire ) ;
6572 }
6673 }
6774
@@ -77,9 +84,12 @@ impl Parker {
7784 if c:: WaitOnAddress :: is_available ( ) {
7885 // Wait for something to happen, assuming it's still set to PARKED.
7986 c:: WaitOnAddress ( self . ptr ( ) , & PARKED as * const _ as c:: LPVOID , 1 , dur2timeout ( timeout) ) ;
80- // Change NOTIFIED=>EMPTY and return in that case.
87+ // Set the state back to EMPTY (from either PARKED or NOTIFIED).
88+ // Note that we don't just write EMPTY, but use swap() to also
89+ // include a acquire-ordered read to synchronize with unpark()'s
90+ // release-ordered write.
8191 if self . state . swap ( EMPTY , Acquire ) == NOTIFIED {
82- return ;
92+ // Actually woken up by unpark().
8393 } else {
8494 // Timeout or spurious wake up.
8595 // We return either way, because we can't easily tell if it was the
@@ -97,17 +107,17 @@ impl Parker {
97107 } ;
98108
99109 // Wait for unpark() to produce this event.
100- if c:: NtWaitForKeyedEvent ( handle, self . ptr ( ) , 0 , & mut timeout) == c:: STATUS_SUCCESS {
101- // Awoken by another thread.
102- self . state . swap ( EMPTY , Acquire ) ;
103- } else {
104- // Not awoken by another thread (spurious or timeout).
105- if self . state . swap ( EMPTY , Acquire ) == NOTIFIED {
106- // If the state is NOTIFIED, we *just* missed an unpark(),
107- // which is now waiting for us to wait for it.
108- // Wait for it to consume the event and unblock it.
109- c :: NtWaitForKeyedEvent ( handle , self . ptr ( ) , 0 , ptr :: null_mut ( ) ) ;
110- }
110+ let unparked = c:: NtWaitForKeyedEvent ( handle, self . ptr ( ) , 0 , & mut timeout) == c:: STATUS_SUCCESS ;
111+
112+ // Set the state back to EMPTY (from either PARKED or NOTIFIED).
113+ let prev_state = self . state . swap ( EMPTY , Acquire ) ;
114+
115+ if !unparked && prev_state == NOTIFIED {
116+ // We were awoken by a timeout, not by unpark(), but the state
117+ // was set to NOTIFIED, which means we *just* missed an
118+ // unpark(), which is now blocked on us to wait for it.
119+ // Wait for it to consume the event and unblock that thread.
120+ c :: NtWaitForKeyedEvent ( handle , self . ptr ( ) , 0 , ptr :: null_mut ( ) ) ;
111121 }
112122 }
113123 }
0 commit comments