@@ -889,7 +889,7 @@ impl Drop for PanicGuard {
889889/// it is guaranteed that this function will not panic (it may abort the
890890/// process if the implementation encounters some rare errors).
891891///
892- /// # park and unpark
892+ /// # ` park` and ` unpark`
893893///
894894/// Every thread is equipped with some basic low-level blocking support, via the
895895/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
@@ -910,14 +910,6 @@ impl Drop for PanicGuard {
910910/// if it wasn't already. Because the token is initially absent, [`unpark`]
911911/// followed by [`park`] will result in the second call returning immediately.
912912///
913- /// In other words, each [`Thread`] acts a bit like a spinlock that can be
914- /// locked and unlocked using `park` and `unpark`.
915- ///
916- /// Notice that being unblocked does not imply any synchronization with someone
917- /// that unparked this thread, it could also be spurious.
918- /// For example, it would be a valid, but inefficient, implementation to make both [`park`] and
919- /// [`unpark`] return immediately without doing anything.
920- ///
921913/// The API is typically used by acquiring a handle to the current thread,
922914/// placing that handle in a shared data structure so that other threads can
923915/// find it, and then `park`ing in a loop. When some desired condition is met, another
@@ -931,6 +923,23 @@ impl Drop for PanicGuard {
931923///
932924/// * It can be implemented very efficiently on many platforms.
933925///
926+ /// # Memory Ordering
927+ ///
928+ /// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory
929+ /// operations performed before a call to `unpark` are made visible to the thread that
930+ /// consumes the token and returns from `park`. Note that all `park` and `unpark`
931+ /// operations for a given thread form a total order and `park` synchronizes-with
932+ /// _all_ prior `unpark` operations.
933+ ///
934+ /// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
935+ /// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
936+ /// thread form a [release sequence].
937+ ///
938+ /// Note that being unblocked does not imply a call was made to `unpark`, because
939+ /// wakeups can also be spurious. For example, a valid, but inefficient,
940+ /// implementation could have `park` and `unpark` return immediately without doing anything,
941+ /// making *all* wakeups spurious.
942+ ///
934943/// # Examples
935944///
936945/// ```
@@ -944,7 +953,7 @@ impl Drop for PanicGuard {
944953/// let parked_thread = thread::spawn(move || {
945954/// // We want to wait until the flag is set. We *could* just spin, but using
946955/// // park/unpark is more efficient.
947- /// while !flag2.load(Ordering::Acquire ) {
956+ /// while !flag2.load(Ordering::Relaxed ) {
948957/// println!("Parking thread");
949958/// thread::park();
950959/// // We *could* get here spuriously, i.e., way before the 10ms below are over!
@@ -961,7 +970,7 @@ impl Drop for PanicGuard {
961970/// // There is no race condition here, if `unpark`
962971/// // happens first, `park` will return immediately.
963972/// // Hence there is no risk of a deadlock.
964- /// flag.store(true, Ordering::Release );
973+ /// flag.store(true, Ordering::Relaxed );
965974/// println!("Unpark the thread");
966975/// parked_thread.thread().unpark();
967976///
@@ -970,6 +979,7 @@ impl Drop for PanicGuard {
970979///
971980/// [`unpark`]: Thread::unpark
972981/// [`thread::park_timeout`]: park_timeout
982+ /// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
973983#[ stable( feature = "rust1" , since = "1.0.0" ) ]
974984pub fn park ( ) {
975985 let guard = PanicGuard ;
0 commit comments