coroutine only.Expand description
§Coroutines (Async)
cu is designed to have flexible coroutine handling. For example, consider these program styles:
- everything being
async- typically involving both CPU-bound work and IO work interwined. Can take advantage of multiple background threads. - Some IO heavy work that doesn’t really involve CPU - for example, spawning compiler processes and wait for them, or spawning network requests. Usually won’t have significant performance benefit from having multiple background threads.
- Heavy CPU work that only has a little IO. Using
asyncusually has very little benefit. (Would probably use something likerayonto get parallelism).
You pick the style you want.
The async runtime being used under the hood is tokio.
There are 2 feature flags you can choose from: coroutine and coroutine-heavy.
coroutine uses one foreground (current-thread) tokio runtime and one background thread to
drive IO tasks. coroutine-heavy does not have a current-thread runtime - everything
is done on the multi-threaded, background runtime.
§Async entry point
To make your entire program async with cli,
simply make the main function `async.
use std::time::Duration;
#[cu::cli]
async fn main(_: cu::cli::Flags) -> cu::Result<()> {
cu::info!("doing some work");
tokio::time::sleep(Duration::from_millis(100)).await;
cu::info!("done");
Ok(())
}When using coroutine, the main future will be spawned onto the current-thread
runtime (so the main thread is still driving it). When using coroutine-heavy,
the main future is spawned onto the background runtime, and the main thread
waits until the future is completed.
§Coroutines used internally and co_* APIs
Some cu functions use coroutines internally behind “synchronous” APIs,
allowing seamless integration from a synchronous context.
For example, when spawning child processes, an async task processes IO from the child and streams results to the main thread. This allows for a clean API to for example, read child’s output line-by-line.
However, there is an important catch - it is crucial that we never block an async runtime. This means to wait for a future:
- If we are not in an async runtime, we can enter the async runtime by
calling an entry point to the runtime (a.k.a
block), to block the current thread while letting the runtime run until the future is finished. - If we are already in an async runtime, we must call
.awaitinstead of block. Otherwise, either the entire runtime will block and may deadlock, or tokio will detect it and panic.
This is why the APIs that use coroutine under the hood will have
another version with a co_* prefix. For example, spawn and co_spawn.
You MUST use .spawn()? if not in an async runtime, and .co_spawn().await?
in an async runtime. Note that calling .co_spawn() while not in an async runtime
is also not allowed, because tokio will assume a runtime is active and panic
if not.
§Advanced Usage
If additional functionality from tokio is needed (not already provided by re-exports),
then you can add tokio to Cargo.toml:
[dependencies]
tokio = "1"Macros§
- join
- Waits on multiple concurrent branches, returning when all branches complete.
- select
- Waits on multiple concurrent branches, returning when the first branch completes, cancelling the remaining branches.
- try_
join - Waits on multiple concurrent branches, returning when all branches
complete with
Ok(_)or on the firstErr(_).
Structs§
- Handle
- Join handle for async task
- Pool
- A pool for limiting async tasks
- Robust
Abort Handle - Robust
Handle - Join handle for async task, like
Handle, with a more robust mechanism for aborting. - Set
- A set of
Handles that can be joined concurrently.
Functions§
- pool
- Create a new
Pool. - run
- Run an async task using the background runtime
- set
- Create a set of handles, that can be joined concurrently.
- set_
flatten - Create a set of handles, that can be joined concurrently.
- sleep
- Waits until
durationhas elapsed. - spawn
- Spawn a task onto the background runtime
- spawn_
blocking coroutine-heavy - Spawn a task onto the blocking pool of the background runtime