Skip to content

Concurrent composition and structured concurrency chapters #252

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
- [Async and await](part-guide/async-await.md)
- [More async/await topics](part-guide/more-async-await.md)
- [IO and issues with blocking](part-guide/io.md)
- [Concurrency primitives](part-guide/concurrency-primitives.md)
- [Composing futures concurrently](part-guide/concurrency-primitives.md)
- [Channels, locking, and synchronization](part-guide/sync.md)
- [Tools for async programming](part-guide/tools.md)
- [Destruction and clean-up](part-guide/dtors.md)
Expand All @@ -31,13 +31,13 @@
- [async in sync, sync in async]()
- [Async IO: readiness vs completion, and io_uring]()
- [Design patterns]()
- [Cancellation]() (cancellation safety)
- [Cancellation and cancellation safety](part-reference/cancellation.md) (cancellation safety)
- [Starvation]()
- [Pinning]()
- [Async and FFI]()
- [Comparing async programming in Rust to other languages]()
- [The implementation of async/await in rustc]()
- [Structured concurrency?]()
- [Structured concurrency](part-reference/structured.md)


# Old chapters
Expand Down
6 changes: 6 additions & 0 deletions src/navigation/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@

- [Cancellation](../part-guide/more-async-await.md#cancellation)
- [`CancellationToken`](../part-guide/more-async-await.md#cancellation)
- [In `select`](../part-guide/concurrency-primitives.md#race-select)
- [Concurrency](../part-guide/concurrency.md)
- [c.f., parallelism](../part-guide/concurrency.md#concurrency-and-parallelism)
- [Primitives (`join`, `select`, etc.)](../part-guide/concurrency-primitives.md)



Expand All @@ -38,6 +40,7 @@



- [`join`](../part-guide/concurrency-primitives.md#join)
- [Joining tasks](../part-guide/async-await.md#joining-tasks)
- [`JoinHandle`](../part-guide/async-await.md#joinhandle)
- [`abort`](../part-guide/more-async-await.md#cancellation)
Expand All @@ -55,12 +58,14 @@



- [`race`](../part-guide/concurrency-primitives.md#race-select)
- [Reactor](../part-guide/async-await.md#the-runtime)
- [Runtimes](../part-guide/async-await.md#the-runtime)



- [Scheduler](../part-guide/async-await.md#the-runtime)
- [`select`](../part-guide/concurrency-primitives.md#race-select)
- [Spawning tasks](../part-guide/async-await.md#spawning-tasks)


Expand All @@ -74,3 +79,4 @@
- Traits
- [async](../part-guide/more-async-await.md#async-traits)
- `Future`
[`try_join`](../part-guide/concurrency-primitives.md#join)
5 changes: 5 additions & 0 deletions src/navigation/topics.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@

- [Introduction](../part-guide/concurrency.md#concurrency-and-parallelism)
- [Running async tasks in parallel using `spawn`](../part-guide/async-await.md#spawning-tasks)
- [Running futures concurrently using `join` and `select`](../part-guide/concurrency-primitives.md)


## Correctness and safety

- Cancellation
- [Introduction](../part-guide/more-async-await.md#cancellation)
- [In `select` and `try_join`](../part-guide/concurrency-primitives.md)


## Performance

- Blocking
- [Introduction](../part-guide/more-async-await.md#blocking-and-cancellation)


## Testing

- [Unit test syntax](../part-guide/more-async-await.md#unit-tests)
7 changes: 6 additions & 1 deletion src/part-guide/async-await.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ That's it! You're ready to write some asynchronous code!

The `#[tokio::main]` annotation initializes the Tokio runtime and starts an async task for running the code in `main`. Later in this guide we'll explain in more detail what that annotation is doing and how to use async code without it (which will give you more flexibility).

### Futures-rs and the ecosystem

TODO context and history, what futures-rs is for - was used a lot, probably don't need it now, overlap with Tokio and other runtimes (sometimes with subtle semantic differences), why you might need it (working with futures directly, esp writing your own, streams, some utils)

Other ecosystem stuff - Yosh's crates, alt runtimes, experimental stuff, other?

### Futures and tasks

Expand Down Expand Up @@ -197,4 +202,4 @@ If we immediately `await`ed the `JoinHandle` of the first `spawn` rather than sa

We'll quickly look at `JoinHandle` in a little more depth. The fact that we can `await` a `JoinHandle` is a clue that a `JoinHandle` is itself a future. `spawn` is not an `async` function, it's a regular function that returns a future (`JoinHandle`). It does some work (to schedule the task) before returning the future (unlike an async future), which is why we don't *need* to `await` `spawn`. Awaiting a `JoinHandle` waits for the spawned task to complete and then returns the result. In the above example, there was no result, we just waited for the task to complete. `JoinHandle` is a generic type and it's type parameter is the type returned by the spawned task. In the above example, the type would be `JoinHandle<()>`, a future that results in a `String` would produce a `JoinHandle` with type `JoinHandle<String>`.

`await`ing a `JoinHandle` returns a `Result` (which is why we used `let _ = ...` in the above example, it avoids a warning about an unused `Result`). If the spawned task completed successfully, then the task's result will be in the `Ok` variant. If the task panicked or was aborted (a form of cancellation, see [TODO]()), then the result will be an `Err` containing a [`JoinError` docs](https://docs.rs/tokio/latest/tokio/task/struct.JoinError.html). If you are not using cancellation via `abort` in your project, then `unwrapping` the result of `JoinHandle.await` is a reasonable approach, since that is effectively propagating a panic from the spawned task to the spawning task.
`await`ing a `JoinHandle` returns a `Result` (which is why we used `let _ = ...` in the above example, it avoids a warning about an unused `Result`). If the spawned task completed successfully, then the task's result will be in the `Ok` variant. If the task panicked or was aborted (a form of [cancellation](../part-reference/cancellation.md)), then the result will be an `Err` containing a [`JoinError` docs](https://docs.rs/tokio/latest/tokio/task/struct.JoinError.html). If you are not using cancellation via `abort` in your project, then `unwrapping` the result of `JoinHandle.await` is a reasonable approach, since that is effectively propagating a panic from the spawned task to the spawning task.
Loading