Skip to main content

pistonite_cu/co/
mod.rs

1//! # Coroutines (Async)
2//!
3//! `cu` is designed to have flexible coroutine handling. For example, consider these program styles:
4//! - everything being `async` - typically involving both CPU-bound
5//!   work and IO work interwined. Can take advantage of multiple background threads.
6//! - Some IO heavy work that doesn't really involve CPU - for example,
7//!   spawning compiler processes and wait for them, or spawning network requests.
8//!   Usually won't have significant performance benefit from having multiple background threads.
9//! - Heavy CPU work that only has a little IO. Using `async` usually has very little
10//!   benefit. (Would probably use something like `rayon` to get parallelism).
11//!
12//! You pick the style you want.
13//!
14//! The async runtime being used under the hood is [`tokio`](https://docs.rs/tokio).
15//! There are 2 feature flags you can choose from: `coroutine` and `coroutine-heavy`.
16//! `coroutine` uses one foreground (current-thread) tokio runtime and one background thread to
17//! drive IO tasks. `coroutine-heavy` does not have a current-thread runtime - everything
18//! is done on the multi-threaded, background runtime.
19//!
20//! # Async entry point
21//!
22//! To make your entire program async with [`cli`](module@crate::cli),
23//! simply make the `main` function `async.
24//!
25//! ```rust
26//! use std::time::Duration;
27//! # use pistonite_cu as cu;
28//! #[cu::cli]
29//! async fn main(_: cu::cli::Flags) -> cu::Result<()> {
30//!     cu::info!("doing some work");
31//!     tokio::time::sleep(Duration::from_millis(100)).await;
32//!     cu::info!("done");
33//!     Ok(())
34//! }
35//! ```
36//!
37//! When using `coroutine`, the main future will be spawned onto the current-thread
38//! runtime (so the main thread is still driving it). When using `coroutine-heavy`,
39//! the main future is spawned onto the background runtime, and the main thread
40//! waits until the future is completed.
41//!
42//! # Coroutines used internally and `co_*` APIs
43//! Some `cu` functions use coroutines internally behind "synchronous" APIs,
44//! allowing seamless integration from a synchronous context.
45//!
46//! For example, when spawning child processes, an async task processes
47//! IO from the child and streams results to the main thread. This allows
48//! for a clean API to for example, read child's output line-by-line.
49//!
50//! However, there is an important catch - it is crucial that we never block
51//! an async runtime. This means to wait for a future:
52//! - If we are not in an async runtime, we can enter the async runtime by
53//!   calling an entry point to the runtime (a.k.a `block`), to block
54//!   the current thread while letting the runtime run until the future is finished.
55//! - If we are already in an async runtime, we must call `.await` instead
56//!   of block. Otherwise, either the entire runtime will block and may deadlock,
57//!   or tokio will detect it and panic.
58//!
59//! This is why the APIs that use `coroutine` under the hood will have
60//! another version with a `co_*` prefix. For example, `spawn` and `co_spawn`.
61//! You MUST use `.spawn()?` if not in an async runtime, and `.co_spawn().await?`
62//! in an async runtime. Note that calling `.co_spawn()` while not in an async runtime
63//! is also not allowed, because tokio will assume a runtime is active and panic
64//! if not.
65//!
66//! # Advanced Usage
67//! If additional functionality from `tokio` is needed (not already provided by re-exports),
68//! then you can add `tokio` to `Cargo.toml`:
69//! ```toml
70//! [dependencies]
71//! tokio = "1"
72//! ```
73
74// re-exports
75pub use tokio::{join, select, time::sleep, try_join};
76
77mod runtime;
78#[cfg(not(feature = "coroutine-heavy"))]
79pub use runtime::block;
80#[cfg(feature = "coroutine-heavy")]
81pub use runtime::spawn_blocking;
82pub use runtime::{run, spawn};
83
84mod pool;
85pub use pool::{Pool, Set, pool, set, set_flatten};
86
87mod handle;
88pub use handle::{AbortHandle, Handle, RobustAbortHandle, RobustHandle};
89mod co_util;