Context:
|
if !self.resync.swap(false, Ordering::Relaxed) { |
The potential scenario with two threads:
- Thread A runs line 99,
resync AtomicBool returns false
|
if !self.resync.swap(false, Ordering::Relaxed) { |
- Thread B, the win32 notifier, runs line 61, sets
resync to true
|
resync.store(true, Ordering::Relaxed); |
- Thread B, runs line 62, there is no watcher on the
AtomicWaker yet
- Thread A run lines 100, stores the
Waker
|
self.waker.register(cx.waker()); |
- Thread A returns
Pending
The task running on Thread A will be pending forever, because resync is true while the call to waker.wake() was done before the Waker itself was registered.
Registering the Waker before loading resync would fix this issue, with the added side of effect of possible spurious wakes. However, spurious wakes should always be expected when dealing with Future. Another approach, would be to have both resync and waker inside a mutex, then we can read resync and set the waker on the same critical area.
Context:
if-watch/src/win.rs
Line 99 in 5ad5fda
The potential scenario with two threads:
resyncAtomicBoolreturnsfalseif-watch/src/win.rs
Line 99 in 5ad5fda
resynctotrueif-watch/src/win.rs
Line 61 in 5ad5fda
AtomicWakeryetif-watch/src/win.rs
Line 62 in 5ad5fda
Wakerif-watch/src/win.rs
Line 100 in 5ad5fda
Pendingif-watch/src/win.rs
Line 101 in 5ad5fda
The task running on Thread A will be pending forever, because
resyncistruewhile the call towaker.wake()was done before theWakeritself was registered.Registering the
Wakerbefore loadingresyncwould fix this issue, with the added side of effect of possible spurious wakes. However, spurious wakes should always be expected when dealing withFuture. Another approach, would be to have both resync and waker inside a mutex, then we can read resync and set the waker on the same critical area.