Skip to content

Commit ec85859

Browse files
authored
Rollup merge of rust-lang#41809 - gamazeps:thread-docs, r=steveklabnik
[DOC] Improve the thread::park and thread::unpark documentation Part of rust-lang#29378 . Takes care of the documentation for `park`, `park_duration` and also improves the `unpark` example. - `park should` have its module documentation inlined here, and cleaned up. - `park_timeout` could use links to `park`.
2 parents a6e1e1f + afe74c3 commit ec85859

File tree

1 file changed

+91
-61
lines changed

1 file changed

+91
-61
lines changed

src/libstd/thread/mod.rs

Lines changed: 91 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -96,41 +96,6 @@
9696
//! The [`thread::current`] function is available even for threads not spawned
9797
//! by the APIs of this module.
9898
//!
99-
//! ## Blocking support: park and unpark
100-
//!
101-
//! Every thread is equipped with some basic low-level blocking support, via the
102-
//! [`thread::park`][`park`] function and [`thread::Thread::unpark()`][`unpark`]
103-
//! method. [`park`] blocks the current thread, which can then be resumed from
104-
//! another thread by calling the [`unpark`] method on the blocked thread's handle.
105-
//!
106-
//! Conceptually, each [`Thread`] handle has an associated token, which is
107-
//! initially not present:
108-
//!
109-
//! * The [`thread::park`][`park`] function blocks the current thread unless or until
110-
//! the token is available for its thread handle, at which point it atomically
111-
//! consumes the token. It may also return *spuriously*, without consuming the
112-
//! token. [`thread::park_timeout`] does the same, but allows specifying a
113-
//! maximum time to block the thread for.
114-
//!
115-
//! * The [`unpark`] method on a [`Thread`] atomically makes the token available
116-
//! if it wasn't already.
117-
//!
118-
//! In other words, each [`Thread`] acts a bit like a semaphore with initial count
119-
//! 0, except that the semaphore is *saturating* (the count cannot go above 1),
120-
//! and can return spuriously.
121-
//!
122-
//! The API is typically used by acquiring a handle to the current thread,
123-
//! placing that handle in a shared data structure so that other threads can
124-
//! find it, and then `park`ing. When some desired condition is met, another
125-
//! thread calls [`unpark`] on the handle.
126-
//!
127-
//! The motivation for this design is twofold:
128-
//!
129-
//! * It avoids the need to allocate mutexes and condvars when building new
130-
//! synchronization primitives; the threads already provide basic blocking/signaling.
131-
//!
132-
//! * It can be implemented very efficiently on many platforms.
133-
//!
13499
//! ## Thread-local storage
135100
//!
136101
//! This module also provides an implementation of thread-local storage for Rust
@@ -568,23 +533,72 @@ pub fn sleep(dur: Duration) {
568533

569534
/// Blocks unless or until the current thread's token is made available.
570535
///
571-
/// Every thread is equipped with some basic low-level blocking support, via
572-
/// the `park()` function and the [`unpark`][unpark] method. These can be
573-
/// used as a more CPU-efficient implementation of a spinlock.
536+
/// A call to `park` does not guarantee that the thread will remain parked
537+
/// forever, and callers should be prepared for this possibility.
538+
///
539+
/// # park and unpark
540+
///
541+
/// Every thread is equipped with some basic low-level blocking support, via the
542+
/// [`thread::park`][`park`] function and [`thread::Thread::unpark`][`unpark`]
543+
/// method. [`park`] blocks the current thread, which can then be resumed from
544+
/// another thread by calling the [`unpark`] method on the blocked thread's
545+
/// handle.
546+
///
547+
/// Conceptually, each [`Thread`] handle has an associated token, which is
548+
/// initially not present:
574549
///
575-
/// [unpark]: struct.Thread.html#method.unpark
550+
/// * The [`thread::park`][`park`] function blocks the current thread unless or
551+
/// until the token is available for its thread handle, at which point it
552+
/// atomically consumes the token. It may also return *spuriously*, without
553+
/// consuming the token. [`thread::park_timeout`] does the same, but allows
554+
/// specifying a maximum time to block the thread for.
555+
///
556+
/// * The [`unpark`] method on a [`Thread`] atomically makes the token available
557+
/// if it wasn't already.
558+
///
559+
/// In other words, each [`Thread`] acts a bit like a spinlock that can be
560+
/// locked and unlocked using `park` and `unpark`.
576561
///
577562
/// The API is typically used by acquiring a handle to the current thread,
578563
/// placing that handle in a shared data structure so that other threads can
579-
/// find it, and then parking (in a loop with a check for the token actually
580-
/// being acquired).
564+
/// find it, and then `park`ing. When some desired condition is met, another
565+
/// thread calls [`unpark`] on the handle.
581566
///
582-
/// A call to `park` does not guarantee that the thread will remain parked
583-
/// forever, and callers should be prepared for this possibility.
567+
/// The motivation for this design is twofold:
568+
///
569+
/// * It avoids the need to allocate mutexes and condvars when building new
570+
/// synchronization primitives; the threads already provide basic
571+
/// blocking/signaling.
584572
///
585-
/// See the [module documentation][thread] for more detail.
573+
/// * It can be implemented very efficiently on many platforms.
586574
///
587-
/// [thread]: index.html
575+
/// # Examples
576+
///
577+
/// ```
578+
/// use std::thread;
579+
/// use std::time::Duration;
580+
///
581+
/// let parked_thread = thread::Builder::new()
582+
/// .spawn(|| {
583+
/// println!("Parking thread");
584+
/// thread::park();
585+
/// println!("Thread unparked");
586+
/// })
587+
/// .unwrap();
588+
///
589+
/// // Let some time pass for the thread to be spawned.
590+
/// thread::sleep(Duration::from_millis(10));
591+
///
592+
/// println!("Unpark the thread");
593+
/// parked_thread.thread().unpark();
594+
///
595+
/// parked_thread.join().unwrap();
596+
/// ```
597+
///
598+
/// [`Thread`]: ../../std/thread/struct.Thread.html
599+
/// [`park`]: ../../std/thread/fn.park.html
600+
/// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
601+
/// [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html
588602
//
589603
// The implementation currently uses the trivial strategy of a Mutex+Condvar
590604
// with wakeup flag, which does not actually allow spurious wakeups. In the
@@ -601,21 +615,21 @@ pub fn park() {
601615
*guard = false;
602616
}
603617

604-
/// Use [park_timeout].
618+
/// Use [`park_timeout`].
605619
///
606620
/// Blocks unless or until the current thread's token is made available or
607621
/// the specified duration has been reached (may wake spuriously).
608622
///
609-
/// The semantics of this function are equivalent to `park()` except that the
610-
/// thread will be blocked for roughly no longer than `ms`. This method
611-
/// should not be used for precise timing due to anomalies such as
623+
/// The semantics of this function are equivalent to [`park`] except
624+
/// that the thread will be blocked for roughly no longer than `dur`. This
625+
/// method should not be used for precise timing due to anomalies such as
612626
/// preemption or platform differences that may not cause the maximum
613627
/// amount of time waited to be precisely `ms` long.
614628
///
615-
/// See the [module documentation][thread] for more detail.
629+
/// See the [park documentation][`park`] for more detail.
616630
///
617-
/// [thread]: index.html
618-
/// [park_timeout]: fn.park_timeout.html
631+
/// [`park_timeout`]: fn.park_timeout.html
632+
/// [`park`]: ../../std/thread/fn.park.html
619633
#[stable(feature = "rust1", since = "1.0.0")]
620634
#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::park_timeout`")]
621635
pub fn park_timeout_ms(ms: u32) {
@@ -625,13 +639,13 @@ pub fn park_timeout_ms(ms: u32) {
625639
/// Blocks unless or until the current thread's token is made available or
626640
/// the specified duration has been reached (may wake spuriously).
627641
///
628-
/// The semantics of this function are equivalent to `park()` except that the
629-
/// thread will be blocked for roughly no longer than `dur`. This method
630-
/// should not be used for precise timing due to anomalies such as
642+
/// The semantics of this function are equivalent to [`park`][park] except
643+
/// that the thread will be blocked for roughly no longer than `dur`. This
644+
/// method should not be used for precise timing due to anomalies such as
631645
/// preemption or platform differences that may not cause the maximum
632646
/// amount of time waited to be precisely `dur` long.
633647
///
634-
/// See the module doc for more detail.
648+
/// See the [park dococumentation][park] for more details.
635649
///
636650
/// # Platform behavior
637651
///
@@ -656,6 +670,8 @@ pub fn park_timeout_ms(ms: u32) {
656670
/// park_timeout(timeout);
657671
/// }
658672
/// ```
673+
///
674+
/// [park]: fn.park.html
659675
#[stable(feature = "park_timeout", since = "1.4.0")]
660676
pub fn park_timeout(dur: Duration) {
661677
let thread = current();
@@ -777,22 +793,36 @@ impl Thread {
777793

778794
/// Atomically makes the handle's token available if it is not already.
779795
///
780-
/// See the module doc for more detail.
796+
/// Every thread is equipped with some basic low-level blocking support, via
797+
/// the [`park`][park] function and the `unpark()` method. These can be
798+
/// used as a more CPU-efficient implementation of a spinlock.
799+
///
800+
/// See the [park documentation][park] for more details.
781801
///
782802
/// # Examples
783803
///
784804
/// ```
785805
/// use std::thread;
806+
/// use std::time::Duration;
786807
///
787-
/// let handler = thread::Builder::new()
808+
/// let parked_thread = thread::Builder::new()
788809
/// .spawn(|| {
789-
/// let thread = thread::current();
790-
/// thread.unpark();
810+
/// println!("Parking thread");
811+
/// thread::park();
812+
/// println!("Thread unparked");
791813
/// })
792814
/// .unwrap();
793815
///
794-
/// handler.join().unwrap();
816+
/// // Let some time pass for the thread to be spawned.
817+
/// thread::sleep(Duration::from_millis(10));
818+
///
819+
/// println!("Unpark the thread");
820+
/// parked_thread.thread().unpark();
821+
///
822+
/// parked_thread.join().unwrap();
795823
/// ```
824+
///
825+
/// [park]: fn.park.html
796826
#[stable(feature = "rust1", since = "1.0.0")]
797827
pub fn unpark(&self) {
798828
let mut guard = self.inner.lock.lock().unwrap();

0 commit comments

Comments
 (0)