Merge pull request #31 from ckaran/master
fix: Removed an extraneous period, and added more explanations of Wakers
This commit is contained in:
@@ -122,11 +122,15 @@ The `Waker` is how the reactor tells the executor that a specific Future is read
|
|||||||
understand the life cycle and ownership of a Waker, you'll understand how futures work from a user's
|
understand the life cycle and ownership of a Waker, you'll understand how futures work from a user's
|
||||||
perspective. Here is the life cycle:
|
perspective. Here is the life cycle:
|
||||||
|
|
||||||
- A Waker is created by the **executor**
|
- A Waker is created by the **executor.** A common, but not required, method is
|
||||||
- When a future is registered with an executor, it’s given a clone of the Waker object created by
|
to create a new Waker for each Future that is registered with the executor.
|
||||||
the executor. Since this is a shared object (e.g. an `Arc<T>`), all clones actually point to the
|
- When a future is registered with an executor, it’s given a clone of the Waker
|
||||||
same underlying object
|
object created by the executor. Since this is a shared object (e.g. an
|
||||||
- The future clones the Waker and passes it to the reactor, which stores it to use later.
|
`Arc<T>`), all clones actually point to the same underlying object. Thus,
|
||||||
|
anything that calls _any_ clone of the original Waker will wake the particular
|
||||||
|
Future that was registered to it.
|
||||||
|
- The future clones the Waker and passes it to the reactor, which stores it to
|
||||||
|
use later.
|
||||||
|
|
||||||
At some point in the future, the reactor will decide that the future is ready to run. It will wake
|
At some point in the future, the reactor will decide that the future is ready to run. It will wake
|
||||||
the future via the Waker that it stored. This action will do what is necessary to get the executor
|
the future via the Waker that it stored. This action will do what is necessary to get the executor
|
||||||
@@ -140,7 +144,7 @@ object).
|
|||||||
|
|
||||||
Since the interface is the same across all executors, reactors can _in theory_ be completely
|
Since the interface is the same across all executors, reactors can _in theory_ be completely
|
||||||
oblivious to the type of the executor, and vice-versa. **Executors and reactors never need to
|
oblivious to the type of the executor, and vice-versa. **Executors and reactors never need to
|
||||||
communicate with one another directly.**.
|
communicate with one another directly.**
|
||||||
|
|
||||||
This design is what gives the futures framework it's power and flexibility and allows the Rust
|
This design is what gives the futures framework it's power and flexibility and allows the Rust
|
||||||
standard library to provide an ergonomic, zero-cost abstraction for us to use.
|
standard library to provide an ergonomic, zero-cost abstraction for us to use.
|
||||||
|
|||||||
@@ -11,6 +11,45 @@ I'll leave you with some suggestions for exercises if you want to explore a litt
|
|||||||
|
|
||||||
Until next time!
|
Until next time!
|
||||||
|
|
||||||
|
## Further notes and comments
|
||||||
|
|
||||||
|
In [Chapter 2](1_futures_in_rust.md), I mentioned that it is common for the
|
||||||
|
executor to create a new Waker for each Future that is registered with the
|
||||||
|
executor, but that the Waker is a shared object similar to a `Arc<T>`. One of
|
||||||
|
the reasons for this design is that it allows different Reactors the ability to
|
||||||
|
Wake a Future. As an example of how this can be used, consider how you could
|
||||||
|
create a new type of Future that has the ability to be canceled. A method of
|
||||||
|
doing this would be to add an
|
||||||
|
[`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html)
|
||||||
|
to the instance of the future, and an extra method called `cancel()`. The
|
||||||
|
`cancel()` method will first set the
|
||||||
|
[`AtomicBool`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html)
|
||||||
|
to signal that the future is now canceled, and then immediately call instance's
|
||||||
|
own copy of the Waker. Once the executor starts executing the Future, the
|
||||||
|
_Future_ will know that it was canceled, and will do the appropriate cleanup
|
||||||
|
actions to terminate itself.
|
||||||
|
|
||||||
|
The main reason for designing the Future in this manner is because we don't have
|
||||||
|
to modify either the Executor or the other Reactors; they are all oblivious to
|
||||||
|
the change. The only possible issue is with the design of the Future itself; a
|
||||||
|
Future that is canceled still needs to terminate correctly according to the
|
||||||
|
rules outlined in the docs for
|
||||||
|
[`Future`](https://doc.rust-lang.org/std/future/trait.Future.html). That means
|
||||||
|
that it can't just delete it's resources and then sit there; it needs to return
|
||||||
|
a value. It is up to you to decide if a canceled future will return
|
||||||
|
[`Pending`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Pending)
|
||||||
|
forever, or if it will return a value in
|
||||||
|
[`Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready). Just
|
||||||
|
be aware that if other Futures are `await`ing it, they won't be able to start
|
||||||
|
until [`Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready)
|
||||||
|
is returned. A common technique for cancelable Futures is to have them return a
|
||||||
|
Result with an error that signals the Future was canceled; that will permit any
|
||||||
|
Futures that are awaiting the canceled Future a chance to progress, with the
|
||||||
|
knowledge that the Future they depended on was canceled. There are additional
|
||||||
|
concerns as well, but beyond the scope of this book. Read the documentation and
|
||||||
|
code for the [`futures`](https://crates.io/crates/futures) crate for a better
|
||||||
|
understanding of what the concerns are.
|
||||||
|
|
||||||
## Reader exercises
|
## Reader exercises
|
||||||
|
|
||||||
So our implementation has taken some obvious shortcuts and could use some improvement.
|
So our implementation has taken some obvious shortcuts and could use some improvement.
|
||||||
|
|||||||
Reference in New Issue
Block a user