use parking_lot::Mutex;
use smol;
use smol_cancellation_token::CancellationToken;
pub struct AsyncTaskSpawner {
token: CancellationToken,
handles: Mutex<Vec<smol::Task<()>>>,
}
impl AsyncTaskSpawner {
#[must_use]
pub fn new() -> Self {
Self {
token: CancellationToken::new(),
handles: Mutex::new(Vec::new()),
}
}
#[must_use]
pub fn builder() -> AsyncTaskSpawnerBuilder {
AsyncTaskSpawnerBuilder::new()
}
pub fn spawn<F, Fut>(&self, task: F)
where
F: FnOnce() -> Fut + Send + 'static,
Fut: std::future::Future<Output = ()> + Send + 'static,
{
if self.token.is_cancelled() {
return;
}
let handle = smol::spawn(async move {
task().await;
});
self.handles.lock().push(handle);
}
pub fn cancel(&self) {
self.token.cancel();
}
pub async fn wait_all(&self) {
let handles = std::mem::take(&mut *self.handles.lock());
for handle in handles {
let () = handle.await;
}
}
#[must_use]
pub fn with_task<F, Fut>(self, task: F) -> Self
where
F: FnOnce() -> Fut + Send + 'static,
Fut: std::future::Future<Output = ()> + Send + 'static,
{
self.spawn(task);
self
}
#[must_use]
pub fn with_cancel(self) -> Self {
self.cancel();
self
}
}
impl Default for AsyncTaskSpawner {
fn default() -> Self {
Self::new()
}
}
pub struct AsyncTaskSpawnerBuilder {
token: Option<CancellationToken>,
}
impl AsyncTaskSpawnerBuilder {
#[must_use]
pub fn new() -> Self {
Self { token: None }
}
#[must_use]
pub fn with_cancellation_token(mut self, token: CancellationToken) -> Self {
self.token = Some(token);
self
}
#[must_use]
pub fn build(self) -> AsyncTaskSpawner {
AsyncTaskSpawner {
token: self.token.unwrap_or_default(),
handles: Mutex::new(Vec::new()),
}
}
}
impl Default for AsyncTaskSpawnerBuilder {
fn default() -> Self {
Self::new()
}
}
pub struct AsyncTaskGroup {
token: CancellationToken,
tasks: Mutex<Vec<smol::Task<()>>>,
}
impl AsyncTaskGroup {
#[must_use]
pub fn new() -> Self {
Self {
token: CancellationToken::new(),
tasks: Mutex::new(Vec::new()),
}
}
pub fn add_task<F, Fut>(&self, task: F)
where
F: FnOnce() -> Fut + Send + 'static,
Fut: std::future::Future<Output = ()> + Send + 'static,
{
if self.token.is_cancelled() {
return;
}
let task_handle = smol::spawn(async move {
task().await;
});
self.tasks.lock().push(task_handle);
}
pub fn cancel(&self) {
self.token.cancel();
}
pub async fn wait_all(&self) {
let tasks = std::mem::take(&mut *self.tasks.lock());
for task in tasks {
let () = task.await;
}
}
}
impl Default for AsyncTaskGroup {
fn default() -> Self {
Self::new()
}
}