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
@@ -547,23 +512,71 @@ pub fn sleep(dur: Duration) {
547512
548513/// Blocks unless or until the current thread's token is made available.
549514///
550- /// Every thread is equipped with some basic low-level blocking support, via
551- /// the `park()` function and the [`unpark`][unpark] method. These can be
552- /// used as a more CPU-efficient implementation of a spinlock.
515+ /// A call to `park` does not guarantee that the thread will remain parked
516+ /// forever, and callers should be prepared for this possibility.
517+ ///
518+ /// # park and unpark
519+ ///
520+ /// Every thread is equipped with some basic low-level blocking support, via the
521+ /// [`thread::park`][`park`] function and [`thread::Thread::unpark()`][`unpark`]
522+ /// method. [`park`] blocks the current thread, which can then be resumed from
523+ /// another thread by calling the [`unpark`] method on the blocked thread's
524+ /// handle.
525+ ///
526+ /// Conceptually, each [`Thread`] handle has an associated token, which is
527+ /// initially not present:
528+ ///
529+ /// * The [`thread::park`][`park`] function blocks the current thread unless or
530+ /// until the token is available for its thread handle, at which point it
531+ /// atomically consumes the token. It may also return *spuriously*, without
532+ /// consuming the token. [`thread::park_timeout`] does the same, but allows
533+ /// specifying a maximum time to block the thread for.
534+ ///
535+ /// * The [`unpark`] method on a [`Thread`] atomically makes the token available
536+ /// if it wasn't already.
553537///
554- /// [unpark]: struct.Thread.html#method.unpark
538+ /// In other words, each [`Thread`] acts a bit like a spinlock that can be
539+ /// locked and unlocked using `park` and `unpark`.
555540///
556541/// The API is typically used by acquiring a handle to the current thread,
557542/// placing that handle in a shared data structure so that other threads can
558- /// find it, and then parking (in a loop with a check for the token actually
559- /// being acquired) .
543+ /// find it, and then `park`ing. When some desired condition is met, another
544+ /// thread calls [`unpark`] on the handle .
560545///
561- /// A call to `park` does not guarantee that the thread will remain parked
562- /// forever, and callers should be prepared for this possibility.
546+ /// The motivation for this design is twofold:
547+ ///
548+ /// * It avoids the need to allocate mutexes and condvars when building new
549+ /// synchronization primitives; the threads already provide basic
550+ /// blocking/signaling.
563551///
564- /// See the [module documentation][thread] for more detail.
552+ /// * It can be implemented very efficiently on many platforms.
553+ ///
554+ /// # Examples
565555///
566- /// [thread]: index.html
556+ /// ```
557+ /// use std::thread;
558+ ///
559+ /// let parked_thread = thread::Builder::new()
560+ /// .spawn(|| {
561+ /// println!("Parking thread");
562+ /// thread::park();
563+ /// println!("Thread unparked");
564+ /// })
565+ /// .unwrap();
566+ ///
567+ /// // Let some time pass for the thread to be spawned.
568+ /// thread::sleep(Duration::from_millis(10));
569+ ///
570+ /// println!("Unpark the thread");
571+ /// parked_thread.thread().unpark();
572+ ///
573+ /// parked_thread.join().unwrap();
574+ /// ```
575+ ///
576+ /// [`Thread`]: ../../std/thread/struct.Thread.html
577+ /// [`park`]: ../../std/thread/fn.park.html
578+ /// [`unpark`]: ../../std/thread/struct.Thread.html#method.unpark
579+ /// [`thread::park_timeout`]: ../../std/thread/fn.park_timeout.html
567580//
568581// The implementation currently uses the trivial strategy of a Mutex+Condvar
569582// with wakeup flag, which does not actually allow spurious wakeups. In the
@@ -591,11 +604,10 @@ pub fn park() {
591604/// preemption or platform differences that may not cause the maximum
592605/// amount of time waited to be precisely `ms` long.
593606///
594- /// See the [module documentation][thread ] for more detail.
607+ /// See the [park documentation][park ] for more detail.
595608///
596- /// [thread]: index.html
597609/// [park_timeout]: fn.park_timeout.html
598- /// [park]: fn.park.html
610+ /// [park]: ../../std/thread/ fn.park.html
599611#[ stable( feature = "rust1" , since = "1.0.0" ) ]
600612#[ rustc_deprecated( since = "1.6.0" , reason = "replaced by `std::thread::park_timeout`" ) ]
601613pub fn park_timeout_ms ( ms : u32 ) {
@@ -611,7 +623,7 @@ pub fn park_timeout_ms(ms: u32) {
611623/// preemption or platform differences that may not cause the maximum
612624/// amount of time waited to be precisely `dur` long.
613625///
614- /// See the [module doc][thread ] for more detail .
626+ /// See the [park dococumentation][park ] for more details .
615627///
616628/// # Platform behavior
617629///
@@ -637,7 +649,6 @@ pub fn park_timeout_ms(ms: u32) {
637649/// }
638650/// ```
639651///
640- /// [thread]: index.html
641652/// [park]: fn.park.html
642653#[ stable( feature = "park_timeout" , since = "1.4.0" ) ]
643654pub fn park_timeout ( dur : Duration ) {
@@ -772,7 +783,7 @@ impl Thread {
772783 /// the [`park()`][park] function and the `unpark()` method. These can be
773784 /// used as a more CPU-efficient implementation of a spinlock.
774785 ///
775- /// See the [module doc][thread ] for more detail .
786+ /// See the [park documentation][park ] for more details .
776787 ///
777788 /// # Examples
778789 ///
@@ -796,7 +807,6 @@ impl Thread {
796807 /// parked_thread.join().unwrap();
797808 /// ```
798809 ///
799- /// [thread]: index.html
800810 /// [park]: fn.park.html
801811 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
802812 pub fn unpark ( & self ) {
0 commit comments