datafusion_common_runtime/join_set.rs
1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements. See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership. The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License. You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied. See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::trace_utils::{trace_block, trace_future};
19use std::future::Future;
20use std::task::{Context, Poll};
21use tokio::runtime::Handle;
22use tokio::task::{AbortHandle, Id, JoinError, LocalSet};
23
24/// A wrapper around [Tokio's `JoinSet`] that forwards all API calls while optionally
25/// instrumenting spawned tasks and blocking closures with custom tracing behavior.
26/// If no tracer is injected via [`set_join_set_tracer`], tasks and closures are executed
27/// without any instrumentation.
28///
29/// [Tokio's `JoinSet`]: tokio::task::JoinSet
30/// [`set_join_set_tracer`]: crate::trace_utils::set_join_set_tracer
31#[derive(Debug)]
32pub struct JoinSet<T> {
33 inner: tokio::task::JoinSet<T>,
34}
35
36impl<T> Default for JoinSet<T> {
37 fn default() -> Self {
38 Self::new()
39 }
40}
41
42impl<T> JoinSet<T> {
43 /// [JoinSet::new](tokio::task::JoinSet::new) - Create a new JoinSet.
44 pub fn new() -> Self {
45 Self {
46 inner: tokio::task::JoinSet::new(),
47 }
48 }
49
50 /// [JoinSet::len](tokio::task::JoinSet::len) - Return the number of tasks.
51 pub fn len(&self) -> usize {
52 self.inner.len()
53 }
54
55 /// [JoinSet::is_empty](tokio::task::JoinSet::is_empty) - Check if the JoinSet is empty.
56 pub fn is_empty(&self) -> bool {
57 self.inner.is_empty()
58 }
59}
60
61impl<T: 'static> JoinSet<T> {
62 /// [JoinSet::spawn](tokio::task::JoinSet::spawn) - Spawn a new task.
63 pub fn spawn<F>(&mut self, task: F) -> AbortHandle
64 where
65 F: Future<Output = T>,
66 F: Send + 'static,
67 T: Send,
68 {
69 self.inner.spawn(trace_future(task))
70 }
71
72 /// [JoinSet::spawn_on](tokio::task::JoinSet::spawn_on) - Spawn a task on a provided runtime.
73 pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
74 where
75 F: Future<Output = T>,
76 F: Send + 'static,
77 T: Send,
78 {
79 self.inner.spawn_on(trace_future(task), handle)
80 }
81
82 /// [JoinSet::spawn_local](tokio::task::JoinSet::spawn_local) - Spawn a local task.
83 pub fn spawn_local<F>(&mut self, task: F) -> AbortHandle
84 where
85 F: Future<Output = T>,
86 F: 'static,
87 {
88 self.inner.spawn_local(task)
89 }
90
91 /// [JoinSet::spawn_local_on](tokio::task::JoinSet::spawn_local_on) - Spawn a local task on a provided LocalSet.
92 pub fn spawn_local_on<F>(&mut self, task: F, local_set: &LocalSet) -> AbortHandle
93 where
94 F: Future<Output = T>,
95 F: 'static,
96 {
97 self.inner.spawn_local_on(task, local_set)
98 }
99
100 /// [JoinSet::spawn_blocking](tokio::task::JoinSet::spawn_blocking) - Spawn a blocking task.
101 pub fn spawn_blocking<F>(&mut self, f: F) -> AbortHandle
102 where
103 F: FnOnce() -> T,
104 F: Send + 'static,
105 T: Send,
106 {
107 self.inner.spawn_blocking(trace_block(f))
108 }
109
110 /// [JoinSet::spawn_blocking_on](tokio::task::JoinSet::spawn_blocking_on) - Spawn a blocking task on a provided runtime.
111 pub fn spawn_blocking_on<F>(&mut self, f: F, handle: &Handle) -> AbortHandle
112 where
113 F: FnOnce() -> T,
114 F: Send + 'static,
115 T: Send,
116 {
117 self.inner.spawn_blocking_on(trace_block(f), handle)
118 }
119
120 /// [JoinSet::join_next](tokio::task::JoinSet::join_next) - Await the next completed task.
121 pub async fn join_next(&mut self) -> Option<Result<T, JoinError>> {
122 self.inner.join_next().await
123 }
124
125 /// [JoinSet::try_join_next](tokio::task::JoinSet::try_join_next) - Try to join the next completed task.
126 pub fn try_join_next(&mut self) -> Option<Result<T, JoinError>> {
127 self.inner.try_join_next()
128 }
129
130 /// [JoinSet::abort_all](tokio::task::JoinSet::abort_all) - Abort all tasks.
131 pub fn abort_all(&mut self) {
132 self.inner.abort_all()
133 }
134
135 /// [JoinSet::detach_all](tokio::task::JoinSet::detach_all) - Detach all tasks.
136 pub fn detach_all(&mut self) {
137 self.inner.detach_all()
138 }
139
140 /// [JoinSet::poll_join_next](tokio::task::JoinSet::poll_join_next) - Poll for the next completed task.
141 pub fn poll_join_next(
142 &mut self,
143 cx: &mut Context<'_>,
144 ) -> Poll<Option<Result<T, JoinError>>> {
145 self.inner.poll_join_next(cx)
146 }
147
148 /// [JoinSet::join_next_with_id](tokio::task::JoinSet::join_next_with_id) - Await the next completed task with its ID.
149 pub async fn join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>> {
150 self.inner.join_next_with_id().await
151 }
152
153 /// [JoinSet::try_join_next_with_id](tokio::task::JoinSet::try_join_next_with_id) - Try to join the next completed task with its ID.
154 pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>> {
155 self.inner.try_join_next_with_id()
156 }
157
158 /// [JoinSet::poll_join_next_with_id](tokio::task::JoinSet::poll_join_next_with_id) - Poll for the next completed task with its ID.
159 pub fn poll_join_next_with_id(
160 &mut self,
161 cx: &mut Context<'_>,
162 ) -> Poll<Option<Result<(Id, T), JoinError>>> {
163 self.inner.poll_join_next_with_id(cx)
164 }
165
166 /// [JoinSet::shutdown](tokio::task::JoinSet::shutdown) - Abort all tasks and wait for shutdown.
167 pub async fn shutdown(&mut self) {
168 self.inner.shutdown().await
169 }
170
171 /// [JoinSet::join_all](tokio::task::JoinSet::join_all) - Await all tasks.
172 pub async fn join_all(self) -> Vec<T> {
173 self.inner.join_all().await
174 }
175}