Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/stdx/src/thread/pool.rs')
| -rw-r--r-- | crates/stdx/src/thread/pool.rs | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/crates/stdx/src/thread/pool.rs b/crates/stdx/src/thread/pool.rs index a8de4db624..8d76c5fd1f 100644 --- a/crates/stdx/src/thread/pool.rs +++ b/crates/stdx/src/thread/pool.rs @@ -8,6 +8,7 @@ //! the threading utilities in [`crate::thread`]. use std::{ + marker::PhantomData, panic::{self, UnwindSafe}, sync::{ Arc, @@ -16,8 +17,9 @@ use std::{ }; use crossbeam_channel::{Receiver, Sender}; +use crossbeam_utils::sync::WaitGroup; -use super::{Builder, JoinHandle, ThreadIntent}; +use crate::thread::{Builder, JoinHandle, ThreadIntent}; pub struct Pool { // `_handles` is never read: the field is present @@ -79,9 +81,6 @@ impl Pool { Self { _handles: handles.into_boxed_slice(), extant_tasks, job_sender } } - /// # Panics - /// - /// Panics if job panics pub fn spawn<F>(&self, intent: ThreadIntent, f: F) where F: FnOnce() + Send + UnwindSafe + 'static, @@ -97,6 +96,17 @@ impl Pool { self.job_sender.send(job).unwrap(); } + pub fn scoped<'pool, 'scope, F, R>(&'pool self, f: F) -> R + where + F: FnOnce(&Scope<'pool, 'scope>) -> R, + { + let wg = WaitGroup::new(); + let scope = Scope { pool: self, wg, _marker: PhantomData }; + let r = f(&scope); + scope.wg.wait(); + r + } + #[must_use] pub fn len(&self) -> usize { self.extant_tasks.load(Ordering::SeqCst) @@ -107,3 +117,36 @@ impl Pool { self.len() == 0 } } + +pub struct Scope<'pool, 'scope> { + pool: &'pool Pool, + wg: WaitGroup, + _marker: PhantomData<fn(&'scope ()) -> &'scope ()>, +} + +impl<'scope> Scope<'_, 'scope> { + pub fn spawn<F>(&self, intent: ThreadIntent, f: F) + where + F: 'scope + FnOnce() + Send + UnwindSafe, + { + let wg = self.wg.clone(); + let f = Box::new(move || { + if cfg!(debug_assertions) { + intent.assert_is_used_on_current_thread(); + } + f(); + drop(wg); + }); + + let job = Job { + requested_intent: intent, + f: unsafe { + std::mem::transmute::< + Box<dyn 'scope + FnOnce() + Send + UnwindSafe>, + Box<dyn 'static + FnOnce() + Send + UnwindSafe>, + >(f) + }, + }; + self.pool.job_sender.send(job).unwrap(); + } +} |