about summary refs log tree commit diff
path: root/library/std/src/thread
diff options
context:
space:
mode:
authorIbraheem Ahmed <ibraheem@ibraheem.ca>2022-07-21 22:49:08 -0400
committerIbraheem Ahmed <ibraheem@ibraheem.ca>2022-07-21 23:09:52 -0400
commit9de1d7c10d4732068d43219253fa8ceccd675754 (patch)
treeee35ea548b4e4f7af78bf2b89a1f1d92c509af92 /library/std/src/thread
parent31b9b012bbced0c47a0ff5e4453cdc2e91e668b2 (diff)
downloadrust-9de1d7c10d4732068d43219253fa8ceccd675754.tar.gz
rust-9de1d7c10d4732068d43219253fa8ceccd675754.zip
document memory orderings of `thread::{park, unpark}`
Diffstat (limited to 'library/std/src/thread')
-rw-r--r--library/std/src/thread/mod.rs28
1 files changed, 19 insertions, 9 deletions
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index d28c7b58b20..32453b4d4a3 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -845,7 +845,7 @@ pub fn sleep(dur: Duration) {
 /// A call to `park` does not guarantee that the thread will remain parked
 /// forever, and callers should be prepared for this possibility.
 ///
-/// # park and unpark
+/// # `park` and `unpark`
 ///
 /// Every thread is equipped with some basic low-level blocking support, via the
 /// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
@@ -866,14 +866,6 @@ pub fn sleep(dur: Duration) {
 ///   if it wasn't already. Because the token is initially absent, [`unpark`]
 ///   followed by [`park`] will result in the second call returning immediately.
 ///
-/// In other words, each [`Thread`] acts a bit like a spinlock that can be
-/// locked and unlocked using `park` and `unpark`.
-///
-/// Notice that being unblocked does not imply any synchronization with someone
-/// that unparked this thread, it could also be spurious.
-/// For example, it would be a valid, but inefficient, implementation to make both [`park`] and
-/// [`unpark`] return immediately without doing anything.
-///
 /// The API is typically used by acquiring a handle to the current thread,
 /// placing that handle in a shared data structure so that other threads can
 /// find it, and then `park`ing in a loop. When some desired condition is met, another
@@ -887,6 +879,23 @@ pub fn sleep(dur: Duration) {
 ///
 /// * It can be implemented very efficiently on many platforms.
 ///
+/// # Memory Orderings
+/// 
+/// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory
+/// operations performed before a call to `unpark` are made visible to the thread that
+/// consumes the token and returns from `park`. Note that all `park` and `unpark`
+/// operations for a given thread form a total order and `park` synchronizes-with
+/// _all_ prior `unpark` operations.
+///
+/// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
+/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
+/// thread form a [release sequence].
+/// 
+/// Notice that being unblocked does not imply any synchronization with someone that
+/// unparked this thread, it could also be spurious. For example, it would be a valid,
+/// but inefficient, implementation to make both park and unpark return immediately
+/// without doing anything.
+///
 /// # Examples
 ///
 /// ```
@@ -926,6 +935,7 @@ pub fn sleep(dur: Duration) {
 ///
 /// [`unpark`]: Thread::unpark
 /// [`thread::park_timeout`]: park_timeout
+/// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn park() {
     // SAFETY: park_timeout is called on the parker owned by this thread.