af_core/
task.rs

1// Copyright © 2020 Alexandra Frydl
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7//! Task-based concurrency.
8
9pub mod join;
10pub mod try_join;
11
12mod cancel;
13
14pub use self::cancel::{CancelSignal, Canceled, Canceler};
15pub use self::join::Join;
16pub use self::try_join::TryJoin;
17
18use crate::prelude::*;
19
20/// Waits for the given duration to elapse.
21pub async fn sleep(duration: Duration) {
22  if duration.is_infinite() {
23    future::forever().await
24  } else {
25    async_io::Timer::after(duration.into()).await;
26  }
27}
28
29/// Starts a new task.
30pub fn start<T>(task: impl Start<T>) -> Task<T>
31where
32  T: Send + 'static,
33{
34  task.start()
35}
36
37/// Starts a new task.
38fn start_impl<T>(future: impl Future<Output = T> + Send + 'static) -> Task<T>
39where
40  T: Send + 'static,
41{
42  let task = async_global_executor::spawn(async move {
43    future::catch_unwind(panic::AssertUnwindSafe(future)).await.map_err(|value| Panic { value })
44  });
45
46  Task { task }
47}
48
49/// Yields once to other running tasks.
50pub async fn yield_now() {
51  futures_lite::future::yield_now().await;
52}
53
54/// An asynchronous task.
55#[must_use = "Tasks are killed when dropped."]
56pub struct Task<T> {
57  task: async_executor::Task<Result<T, Panic>>,
58}
59
60impl<T> Task<T> {
61  /// Kills the task and waits for its future to be dropped.
62  pub async fn kill(self) {
63    self.task.cancel().await;
64  }
65
66  /// Waits for the task to stop and returns its result.
67  pub async fn join(self) -> Result<T, Panic> {
68    self.task.await
69  }
70}
71
72impl<T, E> Task<Result<T, E>>
73where
74  E: From<Panic>,
75{
76  /// Waits for the fallible task to stop and returns its result.
77  pub async fn try_join(self) -> Result<T, E> {
78    self.task.await?
79  }
80}
81
82/// A trait for types that can start tasks.
83pub trait Start<T> {
84  /// Starts a task from this value.
85  fn start(self) -> Task<T>;
86}
87
88impl<T> Start<T> for Task<T> {
89  fn start(self) -> Task<T> {
90    self
91  }
92}
93
94impl<T, F> Start<T> for F
95where
96  T: Send + 'static,
97  F: Future<Output = T> + Send + 'static,
98{
99  fn start(self) -> Task<T> {
100    start_impl(self)
101  }
102}