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
@@ -568,23 +533,72 @@ pub fn sleep(dur: Duration) {
568
533
569
534
/// Blocks unless or until the current thread's token is made available.
570
535
///
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:
574
549
///
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`.
576
561
///
577
562
/// The API is typically used by acquiring a handle to the current thread,
578
563
/// 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 .
581
566
///
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.
584
572
///
585
- /// See the [module documentation][thread] for more detail .
573
+ /// * It can be implemented very efficiently on many platforms .
586
574
///
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
588
602
//
589
603
// The implementation currently uses the trivial strategy of a Mutex+Condvar
590
604
// with wakeup flag, which does not actually allow spurious wakeups. In the
@@ -601,21 +615,21 @@ pub fn park() {
601
615
* guard = false ;
602
616
}
603
617
604
- /// Use [park_timeout].
618
+ /// Use [` park_timeout` ].
605
619
///
606
620
/// Blocks unless or until the current thread's token is made available or
607
621
/// the specified duration has been reached (may wake spuriously).
608
622
///
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
612
626
/// preemption or platform differences that may not cause the maximum
613
627
/// amount of time waited to be precisely `ms` long.
614
628
///
615
- /// See the [module documentation][thread ] for more detail.
629
+ /// See the [park documentation][`park` ] for more detail.
616
630
///
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
619
633
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
620
634
#[ rustc_deprecated( since = "1.6.0" , reason = "replaced by `std::thread::park_timeout`" ) ]
621
635
pub fn park_timeout_ms ( ms : u32 ) {
@@ -625,13 +639,13 @@ pub fn park_timeout_ms(ms: u32) {
625
639
/// Blocks unless or until the current thread's token is made available or
626
640
/// the specified duration has been reached (may wake spuriously).
627
641
///
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
631
645
/// preemption or platform differences that may not cause the maximum
632
646
/// amount of time waited to be precisely `dur` long.
633
647
///
634
- /// See the module doc for more detail .
648
+ /// See the [park dococumentation][park] for more details .
635
649
///
636
650
/// # Platform behavior
637
651
///
@@ -656,6 +670,8 @@ pub fn park_timeout_ms(ms: u32) {
656
670
/// park_timeout(timeout);
657
671
/// }
658
672
/// ```
673
+ ///
674
+ /// [park]: fn.park.html
659
675
#[ stable( feature = "park_timeout" , since = "1.4.0" ) ]
660
676
pub fn park_timeout ( dur : Duration ) {
661
677
let thread = current ( ) ;
@@ -777,22 +793,36 @@ impl Thread {
777
793
778
794
/// Atomically makes the handle's token available if it is not already.
779
795
///
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.
781
801
///
782
802
/// # Examples
783
803
///
784
804
/// ```
785
805
/// use std::thread;
806
+ /// use std::time::Duration;
786
807
///
787
- /// let handler = thread::Builder::new()
808
+ /// let parked_thread = thread::Builder::new()
788
809
/// .spawn(|| {
789
- /// let thread = thread::current();
790
- /// thread.unpark();
810
+ /// println!("Parking thread");
811
+ /// thread::park();
812
+ /// println!("Thread unparked");
791
813
/// })
792
814
/// .unwrap();
793
815
///
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();
795
823
/// ```
824
+ ///
825
+ /// [park]: fn.park.html
796
826
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
797
827
pub fn unpark ( & self ) {
798
828
let mut guard = self . inner . lock . lock ( ) . unwrap ( ) ;
0 commit comments