Skip to content

Instantly share code, notes, and snippets.

@khionu
Last active December 22, 2019 20:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save khionu/d83530e316b34eb6d638f2b51d962307 to your computer and use it in GitHub Desktop.
Save khionu/d83530e316b34eb6d638f2b51d962307 to your computer and use it in GitHub Desktop.
A work-stealing WorkPool using crossbeam-deque
use std::sync::{Arc, RwLock};
use crossbeam_deque::{Injector, Steal, Stealer, Worker};
pub struct WorkPool<T> {
global: Arc<Injector<T>>,
local: Worker<T>,
stealers: Arc<RwLock<Vec<Stealer<T>>>>,
}
impl<T> WorkPool<T> {
pub fn get_work(&self) -> Option<T> {
if let Some(work) = self.local.pop() {
return Some(work);
}
match self.global.steal_batch_and_pop(&self.local) {
Steal::Success(work) => return Some(work),
Steal::Retry => return self.get_work(),
Steal::Empty => {
let mut retry = false;
while retry {
let g = self.stealers.read()
.expect("Poisoned work stealers");
for s in g.iter() {
match s.steal_batch_and_pop(&self.local) {
Steal::Success(work) => return Some(work),
Steal::Retry => retry = true,
_ => {}
}
}
}
None
}
}
}
pub fn push_work(&self, task: T) {
self.global.push(task)
}
pub fn new() -> Self {
let local = Worker::new_fifo();
let stealers = Arc::new(RwLock::new(vec![local.stealer()]));
Self {
local,
stealers,
global: Arc::new(Injector::new()),
}
}
pub fn global(&self) -> Arc<Injector<T>> {
self.global.clone()
}
}
impl<T> Clone for WorkPool<T> {
fn clone(&self) -> Self {
let local = Worker::new_fifo();
self.stealers
.write()
.expect("Poisoned work stealers")
.push(local.stealer());
Self {
local,
global: self.global.clone(),
stealers: self.stealers.clone(),
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment