Struct ste::Thread [−][src]
#[must_use = "The thread should be joined with Thread::join once no longer used, \ otherwise it will block while being dropped."]pub struct Thread { /* fields omitted */ }
The handle for a background thread.
The background thread can be interacted with in a couple of ways:
- submit - for submitted tasks, the call will block until it has been executed on the thread (or the thread has panicked).
- submit_async - for submitting asynchronous tasks, the call will block until it has been executed on the thread (or the thread has panicked).
- drop - for dropping value on the background thread. This is necessary for Tag values that requires drop.
Tasks panicking
If anything on the background thread ends up panicking, the panic will be propagated but also isolated to that one task.
Note that this is only true for unwinding panics. It would not apply to panics resulting in aborts.
Examples
use std::sync::Arc; use std::panic::{AssertUnwindSafe, catch_unwind}; let thread = Arc::new(ste::spawn()); let mut threads = Vec::new(); for n in 0..10 { let thread = thread.clone(); threads.push(std::thread::spawn(move || { thread.submit(move || n) })); } let mut result = 0; for t in threads { result += t.join().unwrap(); } assert_eq!(result, (0..10).sum()); // Unwrap the thread. let thread = Arc::try_unwrap(thread).map_err(|_| "unwrap failed").unwrap(); let result = catch_unwind(AssertUnwindSafe(|| thread.submit(|| { panic!("Background thread: {:?}", std::thread::current().id()); }))); assert!(result.is_err()); println!("Main thread: {:?}", std::thread::current().id()); thread.join();
Implementations
impl Thread
[src]
pub fn submit<F, T>(&self, task: F) -> T where
F: Send + FnOnce() -> T,
T: Send,
[src]
F: Send + FnOnce() -> T,
T: Send,
Submit a task to run on the background thread.
The call will block until it has been executed on the thread (or the thread has panicked).
Because this function blocks until completion, it can safely access values which are outside of the scope of the provided closure.
If you however need to store and access things which are !Send
, you
can wrap them in a container that ensures their thread-locality with
Tag and then safely implement Send for it.
Examples
let thread = ste::spawn(); let mut n = 10; thread.submit(|| n += 10); assert_eq!(20, n); thread.join();
Unwinding panics as isolated on a per-task basis.
use std::panic::{AssertUnwindSafe, catch_unwind}; let thread = ste::spawn(); let result = catch_unwind(AssertUnwindSafe(|| thread.submit(|| panic!("woops")))); assert!(result.is_err()); let mut result = 0; thread.submit(|| { result += 1 }); assert_eq!(result, 1); thread.join();
pub async fn submit_async<F>(&self, future: F) -> F::Output where
F: Send + Future,
F::Output: Send,
[src]
F: Send + Future,
F::Output: Send,
Run the given future on the background thread. The future can reference memory outside of the current scope, but in order to do so, every time it is polled it has to be perfectly synchronized with a remote poll happening on the background thread.
Examples
This method allows the spawned task to access things from its scope,
assuming they are Send
. The actual in the async
task itself though
will run on the background thread.
let thread = ste::Builder::new().with_tokio().build()?; let mut result = 1; thread.submit_async(async { tokio::time::sleep(std::time::Duration::from_secs(1)).await; println!("Hello!"); result += 1; }).await; assert_eq!(result, 2); thread.join();
Panics as isolated on a per-task basis the same was as for submit. They are propagated as a different panic to the calling thread.
let thread = ste::spawn(); thread.submit_async(async move { panic!("woops") }).await; // Note: thread will still join correctly without panicking again.
pub fn drop<T>(&self, value: T) where
T: Send,
[src]
T: Send,
Move the provided value
onto the background thread and drop it.
This is necessary for values which uses Tag to ensure that a type is not dropped incorrectly.
Examples
struct Foo(ste::Tag); impl Drop for Foo { fn drop(&mut self) { self.0.ensure_on_thread(); } } let thread = ste::spawn(); let foo = thread.submit(|| Foo(ste::Tag::current_thread())); thread.drop(foo); thread.join();
pub fn join(self)
[src]
Join the background thread.
Will block until the background thread is joined.
This is the clean way to join a background thread, the alternative is to let Thread drop and this will be performed in the drop handler instead.
Examples
let thread = ste::spawn(); let mut n = 10; thread.submit(|| n += 10); assert_eq!(20, n); thread.join();
pub fn tag(&self) -> Tag
[src]
Construct the tag that is associated with the current thread externally from the thread.
Examples
struct Foo(ste::Tag); impl Foo { fn say_hello(&self) { self.0.ensure_on_thread(); println!("Hello World"); } } let thread = ste::spawn(); let foo = Foo(thread.tag()); thread.submit(|| { foo.say_hello(); }); thread.join();
Trait Implementations
impl Drop for Thread
[src]
impl Send for Thread
[src]
Safety: The handle is both send and sync because it joins the background
thread which keeps track of the state of shared
and cleans it up once it’s
no longer needed.
impl Sync for Thread
[src]
Auto Trait Implementations
Blanket Implementations
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
pub fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> From<T> for T
[src]
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
pub fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,