use parking_lot::Mutex;
pub struct WorkQueue<T, R> {
workers: Vec<crate::channels::core::TxFuture<T>>,
result_rx: crate::channels::core::RxFuture<R>,
next_worker: Mutex<usize>,
}
impl<T: Send + 'static, R: Send + 'static> WorkQueue<T, R> {
#[must_use]
pub fn new(num_workers: usize) -> Self {
let mut workers = Vec::new();
let _result_txs: Vec<crate::channels::core::TxFuture<R>> = Vec::new();
let capacity = (num_workers * 10).max(1); let (result_tx, result_rx) = crate::channels::core::bounded_queue_3(capacity);
for _ in 0..num_workers {
let (task_tx, task_rx) = crate::channels::core::bounded_queue_3(100);
workers.push(task_tx);
let _result_tx = result_tx.clone();
smol::spawn(async move {
let rx = task_rx;
while let Ok(_task) = rx.recv().await {
}
})
.detach();
}
Self {
workers,
result_rx,
next_worker: Mutex::new(0),
}
}
pub async fn submit(&self, task: T) -> Result<(), smol::channel::SendError<T>> {
if self.workers.is_empty() {
return Err(smol::channel::SendError(task));
}
let worker_index = {
let mut next = self.next_worker.lock();
let index = *next % self.workers.len();
*next += 1;
index
};
let worker = &self.workers[worker_index];
worker.send(task).await
}
pub async fn collect(&self) -> Result<R, smol::channel::RecvError> {
self.result_rx.recv().await
}
}