pub mod callback_executor;
pub mod delayed_timer;
pub mod facility;
pub mod future_exec;
pub mod scan_once;
pub mod timer_sleep;
use std::time::Duration;
pub use callback_executor::{
Callback, CallbackError, CallbackHandle, CallbackPool, CallbackPriority, DEFAULT_QUEUE_SIZE,
DEFAULT_THREADS_PER_PRIORITY, NUM_CALLBACK_PRIORITIES,
};
pub use delayed_timer::{DelayedTimer, TimerHandle};
pub use future_exec::{
AbortHandle, DEFAULT_SPAWN_PRIORITY, JoinError, JoinFuture, spawn_blocking_on, spawn_future,
};
pub use scan_once::{
DEFAULT_ONCE_QUEUE_SIZE, OnceCallback, ScanOnceHandle, ScanOnceOverflow, ScanOnceQueue,
};
pub struct BackgroundExecutor {
callbacks: CallbackPool,
timer: DelayedTimer,
scan_once: ScanOnceQueue,
}
impl BackgroundExecutor {
pub fn new() -> Self {
let callbacks = CallbackPool::new();
let timer = DelayedTimer::new(callbacks.handle());
let scan_once = ScanOnceQueue::new();
BackgroundExecutor {
callbacks,
timer,
scan_once,
}
}
pub fn handle(&self) -> BackgroundHandle {
BackgroundHandle {
callbacks: self.callbacks.handle(),
timer: self.timer.handle(),
scan_once: self.scan_once.handle(),
}
}
pub fn callbacks(&self) -> &CallbackPool {
&self.callbacks
}
pub fn timer(&self) -> &DelayedTimer {
&self.timer
}
pub fn scan_once(&self) -> &ScanOnceQueue {
&self.scan_once
}
}
impl Default for BackgroundExecutor {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
pub struct BackgroundHandle {
callbacks: CallbackHandle,
timer: TimerHandle,
scan_once: ScanOnceHandle,
}
impl BackgroundHandle {
pub fn callback(&self, priority: CallbackPriority, cb: Callback) -> Result<(), CallbackError> {
self.callbacks.request(priority, cb)
}
pub fn callback_delayed(&self, delay: Duration, priority: CallbackPriority, cb: Callback) {
self.timer.schedule(delay, priority, cb);
}
pub fn scan_once(&self, cb: OnceCallback) -> Result<(), ScanOnceOverflow> {
self.scan_once.scan_once(cb)
}
pub fn callbacks(&self) -> &CallbackHandle {
&self.callbacks
}
pub fn timer(&self) -> &TimerHandle {
&self.timer
}
pub fn scan_once_handle(&self) -> &ScanOnceHandle {
&self.scan_once
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::mpsc;
const T: Duration = Duration::from_secs(5);
#[test]
fn executor_routes_all_three_facilities() {
let exec = BackgroundExecutor::new();
let h = exec.handle();
let (tx, rx) = mpsc::channel();
let tx_cb = tx.clone();
h.callback(
CallbackPriority::Medium,
Box::new(move || tx_cb.send("cb").unwrap()),
)
.unwrap();
let tx_once = tx.clone();
h.scan_once(Box::new(move || tx_once.send("once").unwrap()))
.unwrap();
h.callback_delayed(
Duration::from_millis(20),
CallbackPriority::High,
Box::new(move || tx.send("delayed").unwrap()),
);
let mut seen = std::collections::HashSet::new();
for _ in 0..3 {
seen.insert(rx.recv_timeout(T).unwrap());
}
assert!(seen.contains("cb"));
assert!(seen.contains("once"));
assert!(seen.contains("delayed"));
}
}