Experiments with structured concurrency in Rust
Similar to rayon, moro let's you create a scope using a moro::async_scope!
macro.
Within this scope, you can spawn jobs that can access stack data defined outside the scope:
let value = 22;
let result = moro::async_scope!(|scope| {
let future1 = scope.spawn(async {
let future2 = scope.spawn(async {
value // access stack values that outlive scope
});
let v = future2.await * 2;
v
});
let v = future1.await * 2;
v
})
.infallible()
.await;
eprintln!("{result}"); // prints 88
Invoke moro::async_scope!(|scope| ...)
and you get back a future
for the overall scope that you can await to start up the scope.
Within the scope body (...
) you can invoke scope.spawn(async { ... })
to spawn a job.
This job must terminate before the scope itself is considered completed.
The result of scope.spawn
is a future whose result is the result returned by the job.
The async_scope!
macro itself optionally supports cancellation.
When you cancel a scope, all the work within that scope immediately
terminates and all futures are dropped (in the future, we'll support
async drop to allow them to do work).
To reflect cancellation, the future you get back from async_scope
has type Result<T, C>
, where T
is the type your scope body returns
and C
is the cancellation type. You cancel a scope by invoking
scope.cancel(c)
.
If your scope is never cancelled, you can use the infallible
method
to create an infallible async scope (whose result is just T
).
An example is shown in the hello world example.
An example that uses cancellation is shown in monitor -- in this example, several jobs are spawned which all examine one integer from the input. If any integers are negative, the entire scope is canceled.
I want to do this. :)