use std::marker::PhantomData;
use std::sync::Barrier;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;
#[derive(Default)]
pub(super) struct Racer<'r> {
tasks: Vec<Box<dyn FnOnce() + Send + 'r>>,
scope: PhantomData<&'r ()>,
}
impl<'r> Racer<'r> {
pub(super) fn add_task<T>(&mut self, task: T)
where
T: FnOnce() + Send + 'r,
{
self.tasks.push(Box::new(task));
}
pub(super) fn execute(self) {
let barrier = &Barrier::new(1 + self.tasks.len());
let fast_flag = &AtomicBool::new(false);
thread::scope(|scope| {
for task in self.tasks {
scope.spawn(move || {
barrier.wait();
while !fast_flag.load(Ordering::Acquire) {
thread::yield_now();
}
task();
});
}
barrier.wait();
fast_flag.store(true, Ordering::Release);
});
}
}