use crossbeam_deque::{
Injector,
Steal,
Stealer,
Worker,
};
use crate::thread_pool::PoolJob;
pub(crate) fn steal_one<S>(source: &S) -> Option<PoolJob>
where
S: QueueStealSource,
{
retry_steal(|| source.steal_one())
}
pub(crate) fn steal_batch_and_pop<S>(source: &S, dest: &Worker<PoolJob>) -> Option<PoolJob>
where
S: QueueStealSource,
{
retry_steal(|| source.steal_batch_and_pop(dest))
}
fn retry_steal<F>(mut steal: F) -> Option<PoolJob>
where
F: FnMut() -> Steal<PoolJob>,
{
loop {
match steal() {
Steal::Success(job) => return Some(job),
Steal::Empty => return None,
Steal::Retry => continue,
}
}
}
pub(crate) trait QueueStealSource {
fn steal_one(&self) -> Steal<PoolJob>;
fn steal_batch_and_pop(&self, dest: &Worker<PoolJob>) -> Steal<PoolJob>;
}
impl QueueStealSource for Injector<PoolJob> {
#[inline]
fn steal_one(&self) -> Steal<PoolJob> {
self.steal()
}
#[inline]
fn steal_batch_and_pop(&self, dest: &Worker<PoolJob>) -> Steal<PoolJob> {
Injector::steal_batch_and_pop(self, dest)
}
}
impl QueueStealSource for Stealer<PoolJob> {
#[inline]
fn steal_one(&self) -> Steal<PoolJob> {
self.steal()
}
#[inline]
fn steal_batch_and_pop(&self, dest: &Worker<PoolJob>) -> Steal<PoolJob> {
Stealer::steal_batch_and_pop(self, dest)
}
}