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`" ) ]
621635pub 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" ) ]
660676pub 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