blob: 1857a4111dbcb8041c07a3167087c4e82793bdde [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
use crate::trace_utils::{trace_block, trace_future};
use std::future::Future;
use std::task::{Context, Poll};
use tokio::runtime::Handle;
use tokio::task::{AbortHandle, Id, JoinError, LocalSet};
/// A wrapper around Tokio's JoinSet that forwards all API calls while optionally
/// instrumenting spawned tasks and blocking closures with custom tracing behavior.
/// If no tracer is injected via `trace_utils::set_tracer`, tasks and closures are executed
/// without any instrumentation.
#[derive(Debug)]
pub struct JoinSet<T> {
inner: tokio::task::JoinSet<T>,
}
impl<T> Default for JoinSet<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> JoinSet<T> {
/// [JoinSet::new](tokio::task::JoinSet::new) - Create a new JoinSet.
pub fn new() -> Self {
Self {
inner: tokio::task::JoinSet::new(),
}
}
/// [JoinSet::len](tokio::task::JoinSet::len) - Return the number of tasks.
pub fn len(&self) -> usize {
self.inner.len()
}
/// [JoinSet::is_empty](tokio::task::JoinSet::is_empty) - Check if the JoinSet is empty.
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
}
impl<T: 'static> JoinSet<T> {
/// [JoinSet::spawn](tokio::task::JoinSet::spawn) - Spawn a new task.
pub fn spawn<F>(&mut self, task: F) -> AbortHandle
where
F: Future<Output = T>,
F: Send + 'static,
T: Send,
{
self.inner.spawn(trace_future(task))
}
/// [JoinSet::spawn_on](tokio::task::JoinSet::spawn_on) - Spawn a task on a provided runtime.
pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
where
F: Future<Output = T>,
F: Send + 'static,
T: Send,
{
self.inner.spawn_on(trace_future(task), handle)
}
/// [JoinSet::spawn_local](tokio::task::JoinSet::spawn_local) - Spawn a local task.
pub fn spawn_local<F>(&mut self, task: F) -> AbortHandle
where
F: Future<Output = T>,
F: 'static,
{
self.inner.spawn_local(task)
}
/// [JoinSet::spawn_local_on](tokio::task::JoinSet::spawn_local_on) - Spawn a local task on a provided LocalSet.
pub fn spawn_local_on<F>(&mut self, task: F, local_set: &LocalSet) -> AbortHandle
where
F: Future<Output = T>,
F: 'static,
{
self.inner.spawn_local_on(task, local_set)
}
/// [JoinSet::spawn_blocking](tokio::task::JoinSet::spawn_blocking) - Spawn a blocking task.
pub fn spawn_blocking<F>(&mut self, f: F) -> AbortHandle
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send,
{
self.inner.spawn_blocking(trace_block(f))
}
/// [JoinSet::spawn_blocking_on](tokio::task::JoinSet::spawn_blocking_on) - Spawn a blocking task on a provided runtime.
pub fn spawn_blocking_on<F>(&mut self, f: F, handle: &Handle) -> AbortHandle
where
F: FnOnce() -> T,
F: Send + 'static,
T: Send,
{
self.inner.spawn_blocking_on(trace_block(f), handle)
}
/// [JoinSet::join_next](tokio::task::JoinSet::join_next) - Await the next completed task.
pub async fn join_next(&mut self) -> Option<Result<T, JoinError>> {
self.inner.join_next().await
}
/// [JoinSet::try_join_next](tokio::task::JoinSet::try_join_next) - Try to join the next completed task.
pub fn try_join_next(&mut self) -> Option<Result<T, JoinError>> {
self.inner.try_join_next()
}
/// [JoinSet::abort_all](tokio::task::JoinSet::abort_all) - Abort all tasks.
pub fn abort_all(&mut self) {
self.inner.abort_all()
}
/// [JoinSet::detach_all](tokio::task::JoinSet::detach_all) - Detach all tasks.
pub fn detach_all(&mut self) {
self.inner.detach_all()
}
/// [JoinSet::poll_join_next](tokio::task::JoinSet::poll_join_next) - Poll for the next completed task.
pub fn poll_join_next(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Option<Result<T, JoinError>>> {
self.inner.poll_join_next(cx)
}
/// [JoinSet::join_next_with_id](tokio::task::JoinSet::join_next_with_id) - Await the next completed task with its ID.
pub async fn join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>> {
self.inner.join_next_with_id().await
}
/// [JoinSet::try_join_next_with_id](tokio::task::JoinSet::try_join_next_with_id) - Try to join the next completed task with its ID.
pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>> {
self.inner.try_join_next_with_id()
}
/// [JoinSet::poll_join_next_with_id](tokio::task::JoinSet::poll_join_next_with_id) - Poll for the next completed task with its ID.
pub fn poll_join_next_with_id(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Option<Result<(Id, T), JoinError>>> {
self.inner.poll_join_next_with_id(cx)
}
/// [JoinSet::shutdown](tokio::task::JoinSet::shutdown) - Abort all tasks and wait for shutdown.
pub async fn shutdown(&mut self) {
self.inner.shutdown().await
}
/// [JoinSet::join_all](tokio::task::JoinSet::join_all) - Await all tasks.
pub async fn join_all(self) -> Vec<T> {
self.inner.join_all().await
}
}