SharedThread

Struct SharedThread 

Source
pub struct SharedThread<T> { /* private fields */ }
Expand description

A wrapper around std::thread::JoinHandle that allows for multiple waiters.

The high-level differences between SharedThread and JoinHandle are:

§Example

use shared_thread::SharedThread;
use std::sync::atomic::{AtomicBool, Ordering::Relaxed};

// Use this flag to tell our shared thread when to stop.
static EXIT_FLAG: AtomicBool = AtomicBool::new(false);

// Start a background thread that we'll share with several waiting threads.
let shared_thread = SharedThread::spawn(|| {
    // Pretend this is some expensive, useful background work...
    while (!EXIT_FLAG.load(Relaxed)) {}

    42
});

// It's up to you how to share the SharedThread object with other threads. In this sense it's
// like any other object you might need to share, like say a HashMap or a File. The common
// options are to put it in an Arc, or to let "scoped" threads borrow it directly. Let's use
// scoped threads.
std::thread::scope(|scope| {
    // Spawn three waiter threads that each wait on the shared thread.
    let waiter1 = scope.spawn(|| shared_thread.join());
    let waiter2 = scope.spawn(|| shared_thread.join());
    let waiter3 = scope.spawn(|| shared_thread.join());

    // In this example, the shared thread is going to keep looping until we set the EXIT_FLAG.
    // In the meantime, .is_finished() returns false, and .try_join() returns None.
    assert!(!shared_thread.is_finished());
    assert_eq!(shared_thread.try_join(), None);

    // Ask the shared thread to stop looping.
    EXIT_FLAG.store(true, Relaxed);

    // Now all the calls to .join() above will return quickly, and each of the waiter threads
    // will get a reference to the shared thread's output, &42.
    assert_eq!(*waiter1.join().unwrap(), 42);
    assert_eq!(*waiter2.join().unwrap(), 42);
    assert_eq!(*waiter3.join().unwrap(), 42);

    // Now that the shared thread has finished, .is_finished() returns true, and .try_join()
    // returns Some(&42).
    assert!(shared_thread.is_finished());
    assert_eq!(*shared_thread.try_join().unwrap(), 42);
});

 // We can take ownership of the output by consuming the SharedThread object. As with any
 // non-Copy type in Rust, this requires that the SharedThread is not borrowed.
 assert_eq!(shared_thread.into_output(), 42);

Implementations§

Source§

impl<T: Send + 'static> SharedThread<T>

Source

pub fn spawn<F>(f: F) -> Self
where F: FnOnce() -> T + Send + 'static,

Spawn a new SharedThread.

§Panics

This function calls std::thread::spawn internally, which panics if it fails to spawn a thread.

Source§

impl<T> SharedThread<T>

Source

pub fn join(&self) -> &T

Wait for the shared thread to finish, then return &T. This blocks the current thread.

§Panics

This function panics if the shared thread panicked. The original panic is propagated directly with resume_unwind the first time. Subsequent calls panic with a generic message.

Source

pub fn join_timeout(&self, timeout: Duration) -> Option<&T>

Wait with a timeout for the shared thread to finish. If it finishes in time (or it already finished), return Some(&T), otherwise return None. This blocks the current thread.

§Panics

This function panics if the shared thread panicked. The original panic is propagated directly with resume_unwind the first time it’s observed. Subsequent calls panic with a generic message.

Source

pub fn join_deadline(&self, deadline: Instant) -> Option<&T>

Wait with a deadline for the shared thread to finish. If it finishes in time (or it already finished), return Some(&T), otherwise return None. This blocks the current thread.

§Panics

This function panics if the shared thread panicked. The original panic is propagated directly with resume_unwind the first time it’s observed. Subsequent calls panic with a generic message.

Source

pub fn try_join(&self) -> Option<&T>

Return Some(&T) if the shared thread has already finished, otherwise None. This always returns quickly.

§Panics

This function panics if the shared thread panicked. The original panic is propagated directly with resume_unwind the first time it’s observed. Subsequent calls panic with a generic message.

Source

pub fn into_output(self) -> T

Wait for the shared thread to finish, then return T. This blocks the current. This requires ownership of the SharedThread and consumes it.

§Panics

This function panics if the shared thread panicked. The original panic is propagated directly with resume_unwind the first time it’s observed. Subsequent calls panic with a generic message.

Source

pub fn is_finished(&self) -> bool

Return true if the shared thread has finished, false otherwise.

This function never blocks. If it returns true, try_join, join_timeout, and join_deadline are guaranteed not to return None, and all join functions are guaranteed to return quickly.

Trait Implementations§

Source§

impl<T: Debug> Debug for SharedThread<T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<T> !Freeze for SharedThread<T>

§

impl<T> RefUnwindSafe for SharedThread<T>

§

impl<T> Send for SharedThread<T>
where T: Send,

§

impl<T> Sync for SharedThread<T>
where T: Sync + Send,

§

impl<T> Unpin for SharedThread<T>
where T: Unpin,

§

impl<T> UnwindSafe for SharedThread<T>
where T: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.