@@ -889,7 +889,7 @@ impl Drop for PanicGuard {
889
889
/// it is guaranteed that this function will not panic (it may abort the
890
890
/// process if the implementation encounters some rare errors).
891
891
///
892
- /// # park and unpark
892
+ /// # ` park` and ` unpark`
893
893
///
894
894
/// Every thread is equipped with some basic low-level blocking support, via the
895
895
/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
@@ -910,14 +910,6 @@ impl Drop for PanicGuard {
910
910
/// if it wasn't already. Because the token is initially absent, [`unpark`]
911
911
/// followed by [`park`] will result in the second call returning immediately.
912
912
///
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
- ///
921
913
/// The API is typically used by acquiring a handle to the current thread,
922
914
/// placing that handle in a shared data structure so that other threads can
923
915
/// find it, and then `park`ing in a loop. When some desired condition is met, another
@@ -931,6 +923,23 @@ impl Drop for PanicGuard {
931
923
///
932
924
/// * It can be implemented very efficiently on many platforms.
933
925
///
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
+ ///
934
943
/// # Examples
935
944
///
936
945
/// ```
@@ -944,7 +953,7 @@ impl Drop for PanicGuard {
944
953
/// let parked_thread = thread::spawn(move || {
945
954
/// // We want to wait until the flag is set. We *could* just spin, but using
946
955
/// // park/unpark is more efficient.
947
- /// while !flag2.load(Ordering::Acquire ) {
956
+ /// while !flag2.load(Ordering::Relaxed ) {
948
957
/// println!("Parking thread");
949
958
/// thread::park();
950
959
/// // We *could* get here spuriously, i.e., way before the 10ms below are over!
@@ -961,7 +970,7 @@ impl Drop for PanicGuard {
961
970
/// // There is no race condition here, if `unpark`
962
971
/// // happens first, `park` will return immediately.
963
972
/// // Hence there is no risk of a deadlock.
964
- /// flag.store(true, Ordering::Release );
973
+ /// flag.store(true, Ordering::Relaxed );
965
974
/// println!("Unpark the thread");
966
975
/// parked_thread.thread().unpark();
967
976
///
@@ -970,6 +979,7 @@ impl Drop for PanicGuard {
970
979
///
971
980
/// [`unpark`]: Thread::unpark
972
981
/// [`thread::park_timeout`]: park_timeout
982
+ /// [release sequence]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release_sequence
973
983
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
974
984
pub fn park ( ) {
975
985
let guard = PanicGuard ;
0 commit comments