96
96
//! The [`thread::current`] function is available even for threads not spawned
97
97
//! by the APIs of this module.
98
98
//!
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
- //!
134
99
//! ## Thread-local storage
135
100
//!
136
101
//! This module also provides an implementation of thread-local storage for Rust
@@ -547,23 +512,71 @@ pub fn sleep(dur: Duration) {
547
512
548
513
/// Blocks unless or until the current thread's token is made available.
549
514
///
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.
553
537
///
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`.
555
540
///
556
541
/// The API is typically used by acquiring a handle to the current thread,
557
542
/// 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 .
560
545
///
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.
563
551
///
564
- /// See the [module documentation][thread] for more detail.
552
+ /// * It can be implemented very efficiently on many platforms.
553
+ ///
554
+ /// # Examples
565
555
///
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
567
580
//
568
581
// The implementation currently uses the trivial strategy of a Mutex+Condvar
569
582
// with wakeup flag, which does not actually allow spurious wakeups. In the
@@ -591,11 +604,10 @@ pub fn park() {
591
604
/// preemption or platform differences that may not cause the maximum
592
605
/// amount of time waited to be precisely `ms` long.
593
606
///
594
- /// See the [module documentation][thread ] for more detail.
607
+ /// See the [park documentation][park ] for more detail.
595
608
///
596
- /// [thread]: index.html
597
609
/// [park_timeout]: fn.park_timeout.html
598
- /// [park]: fn.park.html
610
+ /// [park]: ../../std/thread/ fn.park.html
599
611
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
600
612
#[ rustc_deprecated( since = "1.6.0" , reason = "replaced by `std::thread::park_timeout`" ) ]
601
613
pub fn park_timeout_ms ( ms : u32 ) {
@@ -611,7 +623,7 @@ pub fn park_timeout_ms(ms: u32) {
611
623
/// preemption or platform differences that may not cause the maximum
612
624
/// amount of time waited to be precisely `dur` long.
613
625
///
614
- /// See the [module doc][thread ] for more detail .
626
+ /// See the [park dococumentation][park ] for more details .
615
627
///
616
628
/// # Platform behavior
617
629
///
@@ -637,7 +649,6 @@ pub fn park_timeout_ms(ms: u32) {
637
649
/// }
638
650
/// ```
639
651
///
640
- /// [thread]: index.html
641
652
/// [park]: fn.park.html
642
653
#[ stable( feature = "park_timeout" , since = "1.4.0" ) ]
643
654
pub fn park_timeout ( dur : Duration ) {
@@ -772,7 +783,7 @@ impl Thread {
772
783
/// the [`park()`][park] function and the `unpark()` method. These can be
773
784
/// used as a more CPU-efficient implementation of a spinlock.
774
785
///
775
- /// See the [module doc][thread ] for more detail .
786
+ /// See the [park documentation][park ] for more details .
776
787
///
777
788
/// # Examples
778
789
///
@@ -796,7 +807,6 @@ impl Thread {
796
807
/// parked_thread.join().unwrap();
797
808
/// ```
798
809
///
799
- /// [thread]: index.html
800
810
/// [park]: fn.park.html
801
811
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
802
812
pub fn unpark ( & self ) {
0 commit comments