blob: fdf31ac8d9b3d10de138c6e74932371b5b3db274 [file] [log] [blame]
//! Internal, unsafe APIs for manipulating or querying the current
//! worker thread. Intended for building abstractions atop the
//! rayon-core thread pool, rather than direct use by end users.
use latch::LatchProbe;
use registry;
use std::fmt;
/// Represents the active worker thread.
pub struct WorkerThread<'w> {
thread: &'w registry::WorkerThread,
}
impl<'w> WorkerThread<'w> {
/// Causes the worker thread to wait until `f()` returns true.
/// While the thread is waiting, it will attempt to steal work
/// from other threads, and may go to sleep if there is no work to
/// steal.
///
/// **Dead-lock warning: This is a low-level interface and cannot
/// be used to wait on arbitrary conditions.** In particular, if
/// the Rayon thread goes to sleep, it will only be awoken when
/// new rayon events occur (e.g., `spawn()` or `join()` is
/// invoked, or one of the methods on a `ScopeHandle`). Therefore,
/// you must ensure that, once the condition `f()` becomes true,
/// some "rayon event" will also occur to ensure that waiting
/// threads are awoken.
pub unsafe fn wait_until_true<F>(&self, f: F)
where
F: Fn() -> bool,
{
struct DummyLatch<'a, F: 'a> {
f: &'a F,
}
impl<'a, F: Fn() -> bool> LatchProbe for DummyLatch<'a, F> {
fn probe(&self) -> bool {
(self.f)()
}
}
self.thread.wait_until(&DummyLatch { f: &f });
}
}
impl<'w> fmt::Debug for WorkerThread<'w> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("WorkerThread")
.field("pool", &self.thread.registry().id())
.field("index", &self.thread.index())
.finish()
}
}
/// If the current thread is a Rayon worker thread, then the callback
/// is invoked with a reference to the worker-thread the result of
/// that callback is returned with `Some`. Otherwise, if we are not on
/// a Rayon worker thread, `None` is immediately returned.
pub fn if_in_worker_thread<F, R>(if_true: F) -> Option<R>
where
F: FnOnce(&WorkerThread) -> R,
{
unsafe {
let thread = registry::WorkerThread::current().as_ref()?;
Some(if_true(&WorkerThread { thread }))
}
}