diff --git a/src/async/control-flow/select.md b/src/async/control-flow/select.md index 7e416ea14deb..62d5ac4e451f 100644 --- a/src/async/control-flow/select.md +++ b/src/async/control-flow/select.md @@ -69,7 +69,9 @@ async fn main() { * Try adding a deadline to the race, demonstrating selecting different sorts of futures. -* Note that `select!` consumes the futures it is given, and is easiest to use - when every execution of `select!` creates new futures. +* Note that `select!` moves the values it is given. It is easiest to use + when every execution of `select!` creates new futures. An alternative is to + pass `&mut future` instead of the future itself, but this can lead to + issues, further discussed in the pinning slide. diff --git a/src/async/pitfalls/async-traits.md b/src/async/pitfalls/async-traits.md index 93e9ef8aa322..f643b196bde5 100644 --- a/src/async/pitfalls/async-traits.md +++ b/src/async/pitfalls/async-traits.md @@ -48,13 +48,14 @@ async fn main() {
-* The difficulty with `async trait` is in that the resulting `Future` does not - have a size known at compile time, because the size of the `Future` depends - on the implementation. - * `async_trait` is easy to use, but note that it's using heap allocations to - achieve this, and solve the unknow size problem above. This heap allocation - has performance overhead. + achieve this. This heap allocation has performance overhead. + +* The challenges in language support for `async trait` are deep Rust and + probably not worth describing in-depth. Niko Matsakis did a good job of + explaining them in [this + post](https://smallcultfollowing.com/babysteps/blog/2019/10/26/async-fn-in-traits-are-hard/) + if you are interested in digging deeper. * Try creating a new sleeper struct that will sleep for a random amount of time and adding it to the Vec. diff --git a/src/async/pitfalls/pin.md b/src/async/pitfalls/pin.md index 455e19ee7232..a6b92112d171 100644 --- a/src/async/pitfalls/pin.md +++ b/src/async/pitfalls/pin.md @@ -103,8 +103,10 @@ async fn main() { iteration (a fused future would help with this). Update to reset `timeout_fut` every time it expires. -* Box allocates on the heap. In some cases, `tokio::pin!` is also an option, but +* Box allocates on the heap. In some cases, `std::pin::pin!` (only recently + stabilized, with older code often using `tokio::pin!`) is also an option, but that is difficult to use for a future that is reassigned. + * Another alternative is to not use `pin` at all but spawn another task that will send to a `oneshot` channel every 100ms.
diff --git a/src/async/tasks.md b/src/async/tasks.md index e00499f8219a..6aebfa07c9fe 100644 --- a/src/async/tasks.md +++ b/src/async/tasks.md @@ -1,9 +1,9 @@ # Tasks -Runtimes have the concept of a "Task", similar to a thread but much +Runtimes have the concept of a "task", similar to a thread but much less resource-intensive. -A Task has a single top-level Future which the executor polls to make progress. +A task has a single top-level future which the executor polls to make progress. That future may have one or more nested futures that its `poll` method polls, corresponding loosely to a call stack. Concurrency within a task is possible by polling multiple child futures, such as racing a timer and an I/O operation. diff --git a/src/exercises/day-4/async.md b/src/exercises/day-4/async.md deleted file mode 100644 index 14047188461c..000000000000 --- a/src/exercises/day-4/async.md +++ /dev/null @@ -1,3 +0,0 @@ -# Exercises - -TBD