Структура JoinSet
pub struct JoinSet<T> { /* private fields */ }
rt.Коллекция задач, запущенных в среде выполнения Tokio.
JoinSet можно использовать, чтобы дождаться завершения некоторых или всех задач в наборе. Задачи не упорядочены и возвращаются в порядке их завершения.
Все задачи должны иметь один и тот же тип возвращаемого значения T.
При удалении JoinSet все задачи в JoinSet немедленно прерываются.
Примеры
Запуск нескольких задач и ожидание их завершения.
use tokio::task::JoinSet;
let mut set = JoinSet::new();
for i in 0..10 {
set.spawn(async move { i });
}
let mut seen = [false; 10];
while let Some(res) = set.join_next().await {
let idx = res.unwrap();
seen[idx] = true;
}
for i in 0..10 {
assert!(seen[i]);
}Гарантии для идентификаторов задач
Пока задача отслеживается в JoinSet, её идентификатор уникален относительно всех остальных выполняющихся задач в Tokio. Для этих целей отслеживание задачи в JoinSet эквивалентно хранению JoinHandle для неё. Дополнительную информацию см. в документации по идентификатору задачи.
Реализации
pub fn build_task(&mut self) -> Builder<'_, T>
tokio_unstable и только с функцией crate tracing.Возвращает Builder, который можно использовать для настройки задачи перед её запуском в этом JoinSet.
Примеры
use tokio::task::JoinSet;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut set = JoinSet::new();
// Use the builder to configure a task's name before spawning it.
set.build_task()
.name("my_task")
.spawn(async { /* ... */ })?;
Ok(())
}pub fn spawn<F>(&mut self, task: F) -> AbortHandle
Запускает указанную задачу в JoinSet и возвращает AbortHandle, который можно использовать для удалённой отмены задачи.
Указанный future начнёт выполняться в фоновом режиме сразу после вызова этого метода, даже если вы ничего не ожидаете в этом JoinSet.
Паники
Этот метод вызывает панику, если его вызвать вне среды выполнения Tokio.
pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
Запускает указанную задачу в предоставленной среде выполнения и сохраняет её в этом JoinSet, возвращая AbortHandle, который можно использовать для удалённой отмены задачи.
Указанный future начнёт выполняться в фоновом режиме сразу после вызова этого метода, даже если вы ничего не ожидаете в этом JoinSet.
pub fn spawn_local<F>(&mut self, task: F) -> AbortHandlewhere F: Future<Output = T> + 'static,
Запускает указанную задачу в текущем LocalSet или LocalRuntime и сохраняет её в этом JoinSet, возвращая AbortHandle, который можно использовать для удалённой отмены задачи.
Указанный future начнёт выполняться в фоновом режиме сразу после вызова этого метода, даже если вы ничего не ожидаете в этом JoinSet.
Паники
Этот метод вызывает панику, если его вызвать вне LocalSet или LocalRuntime.
pub fn spawn_local_on<F>( &mut self, task: F, local_set: &LocalSet, ) -> AbortHandlewhere F: Future<Output = T> + 'static,
Запускает указанную задачу в предоставленном LocalSet и сохраняет её в этом JoinSet, возвращая AbortHandle, который можно использовать для удалённой отмены задачи.
В отличие от метода spawn_local, этот метод позволяет запускать локальные задачи в LocalSet, который в данный момент не выполняется. Указанный future начнёт выполняться при следующем запуске LocalSet.
pub fn spawn_blocking<F>(&mut self, f: F) -> AbortHandle
Запускает блокирующий код в пуле блокирующих потоков и сохраняет его в этом JoinSet, возвращая AbortHandle, который можно использовать для удалённой отмены задачи.
Примеры
Запуск нескольких блокирующих задач и ожидание их завершения.
use tokio::task::JoinSet;
#[tokio::main]
async fn main() {
let mut set = JoinSet::new();
for i in 0..10 {
set.spawn_blocking(move || { i });
}
let mut seen = [false; 10];
while let Some(res) = set.join_next().await {
let idx = res.unwrap();
seen[idx] = true;
}
for i in 0..10 {
assert!(seen[i]);
}
}Паники
Этот метод вызывает панику, если его вызвать вне среды выполнения Tokio.
pub fn spawn_blocking_on<F>(&mut self, f: F, handle: &Handle) -> AbortHandle
Запускает блокирующий код в пуле потоков для блокирующих операций предоставленной среды выполнения и сохраняет его в этом JoinSet, возвращая AbortHandle, который можно использовать для удалённой отмены задачи.
pub async fn join_next(&mut self) -> Option<Result<T, JoinError>>
Ожидает завершения одной из задач в наборе и возвращает её результат.
Возвращает None, если набор пуст.
Безопасность отмены
Этот метод безопасен при отмене. Если join_next используется в качестве ветви в tokio::select! и первой завершается другая ветвь, гарантируется, что из этого JoinSet не будет удалено ни одной задачи.
pub async fn join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>>
Ожидает завершения одной из задач в наборе и возвращает её результат вместе с идентификатором задачи.
Возвращает None, если набор пуст.
Если этот метод возвращает ошибку, идентификатор задачи, завершившейся с ошибкой, можно получить с помощью метода JoinError::id.
Безопасность отмены
Этот метод безопасен при отмене. Если join_next_with_id используется в качестве ветви в tokio::select! и первой завершается другая ветвь, гарантируется, что из этого JoinSet не будет удалено ни одной задачи.
pub fn try_join_next(&mut self) -> Option<Result<T, JoinError>>
Пытается присоединиться к одной из завершившихся задач в наборе и вернуть её результат.
Возвращает None, если завершившихся задач нет или набор пуст.
pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>>
Пытается присоединиться к одной из завершившихся задач в наборе и вернуть её результат вместе с идентификатором задачи.
Возвращает None, если завершившихся задач нет или набор пуст.
Если этот метод возвращает ошибку, идентификатор задачи, завершившейся с ошибкой, можно получить с помощью метода JoinError::id.
pub async fn shutdown(&mut self)
pub async fn join_all(self) -> Vec<T>
Ожидает завершения всех задач в этом JoinSet и возвращает вектор их результатов.
Результаты будут сохранены в порядке завершения задач, а не в порядке их запуска. Это вспомогательный метод, эквивалентный вызову join_next в цикле. Если какая-либо задача в JoinSet завершится с ошибкой JoinError, этот вызов join_all вызовет панику, а все оставшиеся задачи в JoinSet будут отменены. Чтобы обрабатывать ошибки другим способом, вручную вызывайте join_next в цикле.
Примеры
Запустите несколько задач и дождитесь их завершения join_all.
use tokio::task::JoinSet;
use std::time::Duration;
let mut set = JoinSet::new();
for i in 0..3 {
set.spawn(async move {
tokio::time::sleep(Duration::from_secs(3 - i)).await;
i
});
}
let output = set.join_all().await;
assert_eq!(output, vec![2, 1, 0]);Эквивалентная реализация join_all с использованием join_next и цикла.
use tokio::task::JoinSet;
use std::panic;
let mut set = JoinSet::new();
for i in 0..3 {
set.spawn(async move {i});
}
let mut output = Vec::new();
while let Some(res) = set.join_next().await{
match res {
Ok(t) => output.push(t),
Err(err) if err.is_panic() => panic::resume_unwind(err.into_panic()),
Err(err) => panic!("{err}"),
}
}
assert_eq!(output.len(),3);pub fn abort_all(&mut self)
Прерывает все задачи в этом JoinSet.
При этом задачи не удаляются из JoinSet. Чтобы дождаться отмены задач, следует вызывать join_next в цикле, пока JoinSet не опустеет.
pub fn detach_all(&mut self)
Удаляет все задачи из этого JoinSet, не прерывая их.
Задачи, удалённые этим вызовом, продолжат выполняться в фоновом режиме, даже если JoinSet будет отброшен.
pub fn poll_join_next( &mut self, cx: &mut Context<'_>, ) -> Poll<Option<Result<T, JoinError>>>
Ожидает завершения одной из задач в наборе.
Если этот метод возвращает Poll::Ready(Some(_)), завершившаяся задача удаляется из набора.
Когда метод возвращает Poll::Pending, для Waker в переданном Context планируется пробуждение по завершении задачи в JoinSet. Обратите внимание: при нескольких вызовах poll_join_next пробуждение запланировано только для Waker из Context, переданного при последнем вызове.
Возвращаемое значение
Эта функция возвращает:
-
Poll::Pending, еслиJoinSetне пуст, но сейчас нет задачи с доступным результатом. -
Poll::Ready(Some(Ok(value))), если одна из задач в этомJoinSetзавершилась.value— это возвращаемое значение одной из завершившихся задач. -
Poll::Ready(Some(Err(err))), если одна из задач в этомJoinSetвызвала панику или была прервана.err— этоJoinErrorзадачи, вызвавшей панику или прерванной. -
Poll::Ready(None), еслиJoinSetпуст.
Обратите внимание: этот метод может вернуть Poll::Pending, даже если одна из задач уже завершилась. Это может произойти при исчерпании бюджета кооперативного планирования.
pub fn poll_join_next_with_id( &mut self, cx: &mut Context<'_>, ) -> Poll<Option<Result<(Id, T), JoinError>>>
Ожидает завершения одной из задач в наборе.
Если этот метод возвращает Poll::Ready(Some(_)), завершившаяся задача удаляется из набора.
Когда метод возвращает Poll::Pending, для Waker в переданном Context планируется пробуждение по завершении задачи в JoinSet. Обратите внимание: при нескольких вызовах poll_join_next пробуждение запланировано только для Waker из Context, переданного при последнем вызове.
Возвращаемое значение
Эта функция возвращает:
-
Poll::Pending, еслиJoinSetне пуст, но сейчас нет задачи с доступным результатом. -
Poll::Ready(Some(Ok((id, value)))), если одна из задач в этомJoinSetзавершилась.value— это возвращаемое значение одной из завершившихся задач, аid— идентификатор задачи. -
Poll::Ready(Some(Err(err))), если одна из задач в этомJoinSetвызвала панику или была прервана.err— этоJoinErrorзадачи, вызвавшей панику или прерванной. -
Poll::Ready(None), еслиJoinSetпуст.
Обратите внимание: этот метод может вернуть Poll::Pending, даже если одна из задач уже завершилась. Это может произойти при исчерпании бюджета кооперативного планирования.
Реализации трейтов
impl<T, F> Extend<F> for JoinSet<T>
Дополняет JoinSet будущими значениями из итератора.
Это эквивалентно вызову JoinSet::spawn для каждого элемента итератора.
Примеры
use tokio::task::JoinSet;
#[tokio::main]
async fn main() {
let mut set: JoinSet<_> = (0..5).map(|i| async move { i }).collect();
set.extend((5..10).map(|i| async move { i }));
let mut seen = [false; 10];
while let Some(res) = set.join_next().await {
let idx = res.unwrap();
seen[idx] = true;
}
for i in 0..10 {
assert!(seen[i]);
}
}fn extend<I>(&mut self, iter: I)where I: IntoIterator<Item = F>,
fn extend_one(&mut self, item: A)
extend_one)
fn extend_reserve(&mut self, additional: usize)
extend_one)
impl<T, F> FromIterator<F> for JoinSet<T>
Собирает итератор фьючерсов в JoinSet.
Это эквивалентно вызову JoinSet::spawn для каждого элемента итератора.
Примеры
Основной пример из документации JoinSet также можно записать с помощью collect:
use tokio::task::JoinSet;
let mut set: JoinSet<_> = (0..10).map(|i| async move { i }).collect();
let mut seen = [false; 10];
while let Some(res) = set.join_next().await {
let idx = res.unwrap();
seen[idx] = true;
}
for i in 0..10 {
assert!(seen[i]);
}fn from_iter<I: IntoIterator<Item = F>>(iter: I) -> Self
Автоматические реализации трейтов
impl<T> !RefUnwindSafe for JoinSet<T>
impl<T> !UnwindSafe for JoinSet<T>
impl<T> Freeze for JoinSet<T>
impl<T> Send for JoinSet<T>where T: Send,
impl<T> Sync for JoinSet<T>where T: Send,
impl<T> Unpin for JoinSet<T>
impl<T> UnsafeUnpin for JoinSet<T>
Общие реализации
impl<T> BorrowMut<T> for Twhere T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
impl<T> Instrument for T
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
impl<T> WithSubscriber for T
fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ
Subscriber к этому типу и возвращает обёртку WithDispatch. Подробнее
MIT License
Copyright © Tokio Contributors
https://docs.rs/tokio/1.53.1/tokio/task/join_set/struct.JoinSet.html