join_handle.rs - source
Description: Source of the Rust file `library/std/src/thread/join_handle.rs`.

#
std/thread/
join_handle.rs

    1use super::Result;
    2use super::lifecycle::JoinInner;
    3use super::thread::Thread;
    4use crate::fmt;
    5use crate::sys::{AsInner, IntoInner, thread as imp};
    6
    7/// An owned permission to join on a thread (block on its termination).
    8///
    9/// A `JoinHandle` *detaches* the associated thread when it is dropped, which
    10/// means that there is no longer any handle to the thread and no way to `join`
    11/// on it.
    12///
    13/// Due to platform restrictions, it is not possible to [`Clone`] this
    14/// handle: the ability to join a thread is a uniquely-owned permission.
    15///
    16/// This `struct` is created by the [`thread::spawn`] function and the
    17/// [`thread::Builder::spawn`] method.
    18///
    19/// # Examples
    20///
    21/// Creation from [`thread::spawn`]:
    22///
    23/// ```
    24/// use std::thread;
    25///
    26/// let join_handle: thread::JoinHandle<_> = thread::spawn(|| {
    27///     // some work here
    28/// });
    29/// ```
    30///
    31/// Creation from [`thread::Builder::spawn`]:
    32///
    33/// ```
    34/// use std::thread;
    35///
    36/// let builder = thread::Builder::new();
    37///
    38/// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
    39///     // some work here
    40/// }).unwrap();
    41/// ```
    42///
    43/// A thread being detached and outliving the thread that spawned it:
    44///
    45/// ```no_run
    46/// use std::thread;
    47/// use std::time::Duration;
    48///
    49/// let original_thread = thread::spawn(|| {
    50///     let _detached_thread = thread::spawn(|| {
    51///         // Here we sleep to make sure that the first thread returns before.
    52///         thread::sleep(Duration::from_millis(10));
    53///         // This will be called, even though the JoinHandle is dropped.
    54///         println!("♫ Still alive ♫");
    55///     });
    56/// });
    57///
    58/// original_thread.join().expect("The thread being joined has panicked");
    59/// println!("Original thread is joined.");
    60///
    61/// // We make sure that the new thread has time to run, before the main
    62/// // thread returns.
    63///
    64/// thread::sleep(Duration::from_millis(1000));
    65/// ```
    66///
    67/// [`thread::Builder::spawn`]: super::Builder::spawn
    68/// [`thread::spawn`]: super::spawn
    69#[stable(feature = "rust1", since = "1.0.0")]
    70#[cfg_attr(target_os = "teeos", must_use)]
    71pub struct JoinHandle<T>(pub(super) JoinInner<'static, T>);
    72
    73#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")]
    74unsafe impl<T> Send for JoinHandle<T> {}
    75#[stable(feature = "joinhandle_impl_send_sync", since = "1.29.0")]
    76unsafe impl<T> Sync for JoinHandle<T> {}
    77
    78impl<T> JoinHandle<T> {
    79    /// Extracts a handle to the underlying thread.
    80    ///
    81    /// # Examples
    82    ///
    83    /// ```
    84    /// use std::thread;
    85    ///
    86    /// let builder = thread::Builder::new();
    87    ///
    88    /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
    89    ///     // some work here
    90    /// }).unwrap();
    91    ///
    92    /// let thread = join_handle.thread();
    93    /// println!("thread id: {:?}", thread.id());
    94    /// ```
    95    #[stable(feature = "rust1", since = "1.0.0")]
    96    #[must_use]
    97    pub fn thread(&self) -> &Thread {
    98        self.0.thread()
    99    }
    100
    101    /// Waits for the associated thread to finish.
    102    ///
    103    /// This function will return immediately if the associated thread has already finished.
    104    ///
    105    /// In terms of [atomic memory orderings],  the completion of the associated
    106    /// thread synchronizes with this function returning. In other words, all
    107    /// operations performed by that thread [happen
    108    /// before](https://doc.rust-lang.org/nomicon/atomics.html#data-accesses) all
    109    /// operations that happen after `join` returns.
    110    ///
    111    /// If the associated thread panics, [`Err`] is returned with the parameter given
    112    /// to [`panic!`] (though see the Notes below).
    113    ///
    114    /// [`Err`]: crate::result::Result::Err
    115    /// [atomic memory orderings]: crate::sync::atomic
    116    ///
    117    /// # Panics
    118    ///
    119    /// This function may panic on some platforms if a thread attempts to join
    120    /// itself or otherwise may create a deadlock with joining threads.
    121    ///
    122    /// # Examples
    123    ///
    124    /// ```
    125    /// use std::thread;
    126    ///
    127    /// let builder = thread::Builder::new();
    128    ///
    129    /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
    130    ///     // some work here
    131    /// }).unwrap();
    132    /// join_handle.join().expect("Couldn't join on the associated thread");
    133    /// ```
    134    ///
    135    /// # Notes
    136    ///
    137    /// If a "foreign" unwinding operation (e.g. an exception thrown from C++
    138    /// code, or a `panic!` in Rust code compiled or linked with a different
    139    /// runtime) unwinds all the way to the thread root, the process may be
    140    /// aborted; see the Notes on [`thread::spawn`]. If the process is not
    141    /// aborted, this function will return a `Result::Err` containing an opaque
    142    /// type.
    143    ///
    144    /// [`catch_unwind`]: ../../std/panic/fn.catch_unwind.html
    145    /// [`thread::spawn`]: super::spawn
    146    #[stable(feature = "rust1", since = "1.0.0")]
    147    pub fn join(self) -> Result<T> {
    148        self.0.join()
    149    }
    150
    151    /// Checks if the associated thread has finished running its main function.
    152    ///
    153    /// `is_finished` supports implementing a non-blocking join operation, by checking
    154    /// `is_finished`, and calling `join` if it returns `true`. This function does not block. To
    155    /// block while waiting on the thread to finish, use [`join`][Self::join].
    156    ///
    157    /// This might return `true` for a brief moment after the thread's main
    158    /// function has returned, but before the thread itself has stopped running.
    159    /// However, once this returns `true`, [`join`][Self::join] can be expected
    160    /// to return quickly, without blocking for any significant amount of time.
    161    #[stable(feature = "thread_is_running", since = "1.61.0")]
    162    pub fn is_finished(&self) -> bool {
    163        self.0.is_finished()
    164    }
    165}
    166
    167impl<T> AsInner<imp::Thread> for JoinHandle<T> {
    168    fn as_inner(&self) -> &imp::Thread {
    169        self.0.as_inner()
    170    }
    171}
    172
    173impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
    174    fn into_inner(self) -> imp::Thread {
    175        self.0.into_inner()
    176    }
    177}
    178
    179#[stable(feature = "std_debug", since = "1.16.0")]
    180impl<T> fmt::Debug for JoinHandle<T> {
    181    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    182        f.debug_struct("JoinHandle").finish_non_exhaustive()
    183    }
    184}