@@ -24,9 +24,9 @@ const ASLEEP: u32 = 0b10;
2424// -----------------------------------------------------------------------------
2525// Latch
2626
27- /// A [ Latch] is a signaling mechanism used to indicate when an event has
27+ /// A Latch is a signaling mechanism used to indicate when an event has
2828/// occurred. The latch begins as *unset* (In the `LOCKED` state), and can later
29- /// be *set* by any thread (entering the * SIGNAL* ) state.
29+ /// be *set* by any thread (entering the ` SIGNAL` ) state.
3030///
3131/// Each latch is associated with one *owner thread*. This is the thread that
3232/// may be blocking, waiting for the latch to complete.
@@ -62,10 +62,21 @@ impl Latch {
6262 /// Returns true if the latch signal was received, and false otherwise.
6363 #[ inline( always) ]
6464 pub fn wait ( & self ) -> bool {
65+ // First, check if the latch has been set.
66+ //
67+ // In the event of a race with `set`:
68+ // + If this happens before the store, then we will go to sleep.
69+ // + If this happens after the store, then we notice and return.
6570 if self . state . load ( Ordering :: Relaxed ) == SIGNAL {
6671 return true ;
6772 }
73+ // If it has not been set, go to sleep.
74+ //
75+ // In the event of a race with `set`, the `wake` will always cause this
76+ // to return regardless of memory ordering.
6877 let slept = self . sleep_controller . sleep ( ) ;
78+ // If we actually slept, check the status again to see if it has
79+ // changed. Otherwise assume it hasn't.
6980 if slept {
7081 self . state . load ( Ordering :: Relaxed ) == SIGNAL
7182 } else {
@@ -86,8 +97,16 @@ impl Latch {
8697 pub unsafe fn set ( latch : * const Latch ) {
8798 // SAFETY: At this point, the latch must still be valid to dereference.
8899 let sleep_controller = unsafe { ( * latch) . sleep_controller } ;
100+ // First we set the state to true.
101+ //
102+ // In the event of a race with `wait`, this may cause `wait` to return.
103+ // Otherwise the other thread will sleep within `wait.
104+ //
89105 // SAFETY: At this point, the latch must still be valid to dereference.
90106 unsafe { ( * latch) . state . store ( SIGNAL , Ordering :: Relaxed ) } ;
107+ // We must try to wake the other thread, just in case it missed the
108+ // notification and went to sleep. This garentees that the other thread
109+ // will make progress.
91110 sleep_controller. wake ( ) ;
92111 }
93112
@@ -120,21 +139,59 @@ impl Default for SleepController {
120139}
121140
122141impl SleepController {
142+ // Attempt to wake the thread to which this belongs.
143+ //
144+ // Returns true if this allows the thread to make progress (by waking it up
145+ // or catching it before it goes to sleep) and false if the thread was
146+ // running.
123147 pub fn wake ( & self ) -> bool {
148+ // Set set the state to SIGNAL and read the current state, which must be
149+ // either LOCKED or ASLEEP.
124150 let sleep_state = self . state . swap ( SIGNAL , Ordering :: Relaxed ) ;
125151 let asleep = sleep_state == ASLEEP ;
126152 if asleep {
153+ // If the state was ASLEEP, the thread is either asleep or about to
154+ // go to sleep.
155+ //
156+ // + If it is about to go to sleep (but has not yet called
157+ // `atomic_wait::wait`) then setting the state to SIGNAL above
158+ // should prevent it from going to sleep.
159+ //
160+ // + If it is already waiting, the following notification will wake
161+ // it up.
162+ //
163+ // Either way, after this call the other thread must make progress.
127164 atomic_wait:: wake_one ( & self . state ) ;
128165 }
129166 asleep
130167 }
131168
169+ // Attempt to send the thread to sleep. This should only be called on a
170+ // single thread, and we say that this controller "belongs" to that thread.
171+ //
172+ // Returns true if this thread makes a syscall to suspend the thread, and
173+ // false if the thread was already woken (letting us skip the syscall).
132174 pub fn sleep ( & self ) -> bool {
175+ // Set the state to ASLEEP and read the current state, which must be
176+ // either LOCKED or SIGNAL.
133177 let state = self . state . swap ( ASLEEP , Ordering :: Relaxed ) ;
178+ // If the state is LOCKED, then we have not yet received a signal, and
179+ // we should try to put the thread to sleep. Otherwise we should return
180+ // early.
134181 let sleep = state == LOCKED ;
135182 if sleep {
183+ // If we have received a signal since entering the sleep state
184+ // (meaning the state is not longer set to ASLEEP) then this will
185+ // return emediately.
186+ //
187+ // If the state is still ASLEEP, then the next call to `wake` will
188+ // register that and call `wake_on`.
189+ //
190+ // Either way, there is no way we can fail to receive a `wake`.
136191 atomic_wait:: wait ( & self . state , ASLEEP ) ;
137192 }
193+ // Set the state back to LOCKED so that we are ready to receive new
194+ // signals.
138195 self . state . store ( LOCKED , Ordering :: Relaxed ) ;
139196 sleep
140197 }
0 commit comments