diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index d28c7b58b20ba..32453b4d4a3cb 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.