final audit pass with minor changes
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Generators
|
||||
# Generators and async/await
|
||||
|
||||
>**Overview:**
|
||||
>
|
||||
@@ -10,15 +10,18 @@
|
||||
>well written and I can recommend reading through it (it talks as much about
|
||||
>async/await as it does about generators).
|
||||
|
||||
## Why generators?
|
||||
## Why learn about generators?
|
||||
|
||||
Generators/yield and async/await are so similar that once you understand one
|
||||
you should be able to understand the other.
|
||||
you should be able to understand the other.
|
||||
|
||||
It's much easier for me to provide runnable and short examples using Generators
|
||||
instead of Futures which require us to introduce a lot of concepts now that
|
||||
we'll cover later just to show an example.
|
||||
|
||||
Async/await works like generators but instead of returning a generator it returns
|
||||
a special object implementing the Future trait.
|
||||
|
||||
A small bonus is that you'll have a pretty good introduction to both Generators
|
||||
and Async/Await by the end of this chapter.
|
||||
|
||||
@@ -553,7 +556,7 @@ second.
|
||||
Before we go and explain the problem in detail, let's finish off this chapter
|
||||
by looking at how generators and the async keyword is related.
|
||||
|
||||
## Async blocks and generators
|
||||
## Async and generators
|
||||
|
||||
Futures in Rust are implemented as state machines much the same way Generators
|
||||
are state machines.
|
||||
@@ -582,10 +585,19 @@ let mut fut = async {
|
||||
```
|
||||
|
||||
The difference is that Futures has different states than what a `Generator` would
|
||||
have. The states of a Rust Futures is either: `Pending` or `Ready`.
|
||||
have.
|
||||
|
||||
An async block will return a `Future` instead of a `Generator`, however, the way
|
||||
a Future works and the way a Generator work internally is similar.
|
||||
a Future works and the way a Generator work internally is similar.
|
||||
|
||||
Instead of calling `Generator::resume` we call `Future::poll`, and instead of
|
||||
returning `Yielded` or `Complete` it returns `Pending` or `Ready`. Each `await`
|
||||
point in a future is like a `yield` point in a generator.
|
||||
|
||||
Do you see how they're connected now?
|
||||
|
||||
Thats why kowing how generators work and the challanges they pose also teaches
|
||||
you how futures work and the challenges we need to tackle when working with them.
|
||||
|
||||
The same goes for the challenges of borrowing across yield/await points.
|
||||
|
||||
@@ -648,7 +648,7 @@ two things:
|
||||
|
||||
The last point is relevant when we move on the the last paragraph.
|
||||
|
||||
## Async/Await and concurrent Futures
|
||||
## Async/Await and concurrecy
|
||||
|
||||
The `async` keyword can be used on functions as in `async fn(...)` or on a
|
||||
block as in `async { ... }`. Both will turn your function, or block, into a
|
||||
@@ -657,13 +657,12 @@ block as in `async { ... }`. Both will turn your function, or block, into a
|
||||
These `Futures` are rather simple. Imagine our generator from a few chapters
|
||||
back. Every `await` point is like a `yield` point.
|
||||
|
||||
Instead of `yielding` a value we pass in, it yields the `Future` we're awaiting,
|
||||
so when we poll a future the first time we run the code up until the first
|
||||
`await` point where it yields a new Future we can poll.
|
||||
Instead of `yielding` a value we pass in, we yield the result of calling `poll` on
|
||||
the next `Future` we're awaiting.
|
||||
|
||||
Our `mainfut` contains two non-leaf futures which it awaits, and all that
|
||||
happens is that these state machines are polled until some "leaf future" in the
|
||||
end either returns `Ready` or `Pending`.
|
||||
Our `mainfut` contains two non-leaf futures which it will call `poll` on. **Non-leaf-futures**
|
||||
has a `poll` method that simply polls their inner futures and these state machines
|
||||
are polled until some "leaf future" in the end either returns `Ready` or `Pending`.
|
||||
|
||||
The way our example is right now, it's not much better than regular synchronous
|
||||
code. For us to actually await multiple futures at the same time we somehow need
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
- [Background information](./0_background_information.md)
|
||||
- [Futures in Rust](./1_futures_in_rust.md)
|
||||
- [Waker and Context](./2_waker_context.md)
|
||||
- [Generators](./3_generators_pin.md)
|
||||
- [Generators and async/await](./3_generators_async_await.md)
|
||||
- [Pin](./4_pin.md)
|
||||
- [Implementing Futures](./6_future_example.md)
|
||||
- [Finished example (editable)](./8_finished_example.md)
|
||||
|
||||
@@ -62,7 +62,7 @@ async ecosystem and and rarely gets enough praise in my eyes.
|
||||
|
||||
A special thanks to [jonhoo](https://twitter.com/jonhoo) who was kind enough to
|
||||
give me some valuable feedback on a very early draft of this book. He has not
|
||||
read the finished product, but a thanks is definitely due.
|
||||
read the finished product, but a big thanks is definitely due.
|
||||
|
||||
[mdbook]: https://github.com/rust-lang/mdBook
|
||||
[book_repo]: https://github.com/cfsamson/books-futures-explained
|
||||
|
||||
Reference in New Issue
Block a user