use crate::{Task, TaskQueue};
pub trait Executor {
type Handle: Handle;
fn execute(&self, task: Task, task_queue: TaskQueue<Self::Handle>) -> Self::Handle;
}
pub trait Handle {
type Id;
fn abort(&mut self);
fn is_self(&self, id: &Self::Id) -> bool;
}
#[cfg(test)]
mod tests {
use crate::{Executor, Handle, Task, TaskQueue};
use core::cell::Cell;
struct StubExecutor {
honest: bool,
next_id: Cell<usize>,
}
struct StubHandle {
honest: bool,
id: usize,
}
impl Handle for StubHandle {
type Id = usize;
fn abort(&mut self) {}
fn is_self(&self, id: &Self::Id) -> bool {
self.honest && self.id == *id
}
}
impl Executor for StubExecutor {
type Handle = StubHandle;
fn execute(&self, _task: Task, _queue: TaskQueue<Self::Handle>) -> Self::Handle {
let id = self.next_id.get();
self.next_id.set(id + 1);
StubHandle {
honest: self.honest,
id,
}
}
}
fn queue_with_one_worker(honest: bool) -> TaskQueue<StubHandle> {
let executor = StubExecutor {
honest,
next_id: Cell::new(0),
};
let queue = TaskQueue::new(core::iter::once(0..10));
queue
.set_threads(1, 1, Some(&executor))
.expect("executor provided");
let _ = queue.add(Task::new(10..20));
queue
}
#[test]
fn honest_is_self_lets_the_worker_steal_waiting_work() {
let queue = queue_with_one_worker(true);
let mut task = Task::new(0..0);
assert!(queue.steal(&0, &mut task, 1, 1));
assert_eq!(task.get(), 10..20);
}
#[test]
fn broken_is_self_strands_waiting_work() {
let queue = queue_with_one_worker(false);
let mut task = Task::new(0..0);
assert!(!queue.steal(&0, &mut task, 1, 1));
assert_eq!(task.get(), 0..0);
}
#[test]
fn unregistered_id_cannot_steal() {
let queue = queue_with_one_worker(true);
let mut task = Task::new(0..0);
assert!(!queue.steal(&7, &mut task, 1, 1));
assert_eq!(task.get(), 0..0);
}
}