@@ -49,19 +49,26 @@ impl Parker {
49
49
return ;
50
50
}
51
51
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.
55
55
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
+ }
64
63
}
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 ) ;
65
72
}
66
73
}
67
74
@@ -77,9 +84,12 @@ impl Parker {
77
84
if c:: WaitOnAddress :: is_available ( ) {
78
85
// Wait for something to happen, assuming it's still set to PARKED.
79
86
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.
81
91
if self . state . swap ( EMPTY , Acquire ) == NOTIFIED {
82
- return ;
92
+ // Actually woken up by unpark().
83
93
} else {
84
94
// Timeout or spurious wake up.
85
95
// We return either way, because we can't easily tell if it was the
@@ -97,17 +107,17 @@ impl Parker {
97
107
} ;
98
108
99
109
// 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 ( ) ) ;
111
121
}
112
122
}
113
123
}
0 commit comments