use crate::{Message, Pool, Thunk, WaitGroup};
use std::{marker::PhantomData, sync::Arc};
pub struct Scope<'scope> {
pool: Pool,
wait: Arc<WaitGroup>,
__variance: PhantomData<*mut &'scope ()>,
}
unsafe impl Send for Scope<'_> {}
unsafe impl Sync for Scope<'_> {}
impl<'scope> Scope<'scope> {
#[inline]
pub fn forever(pool: Pool) -> Scope<'static> {
Scope {
pool,
wait: Arc::new(WaitGroup::default()),
__variance: PhantomData,
}
}
pub fn execute<F>(&self, job: F)
where
F: FnOnce() + Send + 'scope,
{
self.wait.submit();
let task = unsafe {
std::mem::transmute::<Thunk<'scope>, Thunk<'static>>(Box::new(job))
};
self.pool
.inner
.msg_tx
.send(Message::Job(task, self.wait.clone()))
.expect("failed to send message via channel");
}
pub fn recurse<F>(&self, job: F)
where
F: FnOnce(&Self) + Send + 'scope,
{
let this = self.private_clone();
self.execute(move || job(&this));
}
pub fn join(&self) {
self.wait.join()
}
pub fn zoom<'smaller, F, R>(&self, job: F) -> R
where
F: FnOnce(&Scope<'smaller>) -> R,
'scope: 'smaller,
{
let scope = self.refine();
scopeguard::defer!(scope.join());
job(&scope)
}
fn private_clone(&self) -> Self {
Scope {
pool: self.pool.clone(),
wait: self.wait.clone(),
__variance: PhantomData,
}
}
fn refine<'other>(&self) -> Scope<'other>
where
'scope: 'other,
{
Scope {
pool: self.pool.clone(),
wait: Arc::new(WaitGroup::default()),
__variance: PhantomData,
}
}
}