Skip to content

Commit a3b8705

Browse files
author
James Duley
committed
Expand synchronization comments in park/unpark
1 parent f8a78bd commit a3b8705

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/libstd/thread/mod.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -800,9 +800,12 @@ pub fn park() {
800800
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
801801
Ok(_) => {}
802802
Err(NOTIFIED) => {
803-
// We must read again here, even though we know it will be NOTIFY,
804-
// to synchronize with an write in `unpark` that occurred since we
805-
// last read.
803+
// We must read here, even though we know it will be `NOTIFIED`.
804+
// This is because `unpark` may have been called again since we read
805+
// `NOTIFIED` in the `compare_exchange` above. We must perform an
806+
// acquire operation that synchronizes with that `unpark` to observe
807+
// any writes it made before the call to unpark. To do that we must
808+
// read from the write it made to `state`.
806809
let old = thread.inner.state.swap(EMPTY, SeqCst);
807810
assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
808811
return;
@@ -893,9 +896,7 @@ pub fn park_timeout(dur: Duration) {
893896
match thread.inner.state.compare_exchange(EMPTY, PARKED, SeqCst, SeqCst) {
894897
Ok(_) => {}
895898
Err(NOTIFIED) => {
896-
// We must read again here, even though we know it will be NOTIFY,
897-
// to synchronize with an write in `unpark` that occurred since we
898-
// last read.
899+
// We must read again here, see `park`.
899900
let old = thread.inner.state.swap(EMPTY, SeqCst);
900901
assert_eq!(old, NOTIFIED, "park state changed unexpectedly");
901902
return;
@@ -1066,8 +1067,12 @@ impl Thread {
10661067
/// [park]: fn.park.html
10671068
#[stable(feature = "rust1", since = "1.0.0")]
10681069
pub fn unpark(&self) {
1069-
// We must unconditionally write NOTIFIED here to
1070-
// synchronize with a read in `park`.
1070+
// To ensure the unparked thread will observe any writes we made
1071+
// before this call, we must perform a release operation that `park`
1072+
// can synchronize with. To do that we must write `NOTIFIED` even if
1073+
// `state` is already `NOTIFIED`. That is why this must be a swap
1074+
// rather than a compare-and-swap that returns if it reads `NOTIFIED`
1075+
// on failure.
10711076
match self.inner.state.swap(NOTIFIED, SeqCst) {
10721077
EMPTY => return, // no one was waiting
10731078
NOTIFIED => return, // already unparked

0 commit comments

Comments
 (0)