Merge pull request #44 from pedromfedricci/docfixes

Fix some links, names and linter warnings
This commit is contained in:
Carl Fredrik Samson
2022-02-02 13:39:13 +01:00
committed by GitHub
7 changed files with 28 additions and 32 deletions

View File

@@ -92,6 +92,7 @@ that they implement a way to do multitasking by having a "userland"
runtime.
## Green threads/stackful coroutines
In this book I'll use the term "green threads" to mean stackful coroutines to differentiate
them from the other continuation mechanisms described in this chapter. You can, however, see
the term "green threads" be used to describe a broader set of continuation mechanisms in different
@@ -108,7 +109,7 @@ Rust had green threads once, but they were removed before it hit 1.0. The state
of execution is stored in each stack so in such a solution there would be no
need for `async`, `await`, `Future` or `Pin`. In many ways, green threads mimics how
an operating system facilitates concurrency, and implementing them is a great
learning experience.
learning experience.
**The typical flow looks like this:**

View File

@@ -107,7 +107,7 @@ you'll just use the one provided for you.
I find it easier to reason about how Futures work by creating a high level mental model we can use.
To do that I have to introduce the concept of a runtime which will drive our Futures to completion.
>Please note that the mental model I create here is not the *only* way to drive Futures to
>Please note that the mental model I create here is not the **only** way to drive Futures to
completion and that Rusts Futures does not impose any restrictions on how you actually accomplish
this task.
@@ -217,7 +217,7 @@ The problem with #2 is that if you switch runtime you need to make sure that it
supports this kind of supervision as well or else you will end up blocking the
executor.
#3 is more of theoretical importance, normally you'd be happy by sending the task
And #3 is more of theoretical importance, normally you'd be happy by sending the task
to the thread-pool most runtimes provide.
Most executors have a way to accomplish #1 using methods like `spawn_blocking`.
@@ -238,10 +238,10 @@ general, I know where you're coming from and I have written some resources to
try to give a high-level overview that will make it easier to learn Rust's
Futures afterwards:
* [Async Basics - The difference between concurrency and parallelism](https://cfsamson.github.io/book-exploring-async-basics/1_concurrent_vs_parallel.html)
* [Async Basics - Async history](https://cfsamson.github.io/book-exploring-async-basics/2_async_history.html)
* [Async Basics - Strategies for handling I/O](https://cfsamson.github.io/book-exploring-async-basics/5_strategies_for_handling_io.html)
* [Async Basics - Epoll, Kqueue and IOCP](https://cfsamson.github.io/book-exploring-async-basics/6_epoll_kqueue_iocp.html)
- [Async Basics - The difference between concurrency and parallelism](https://cfsamson.github.io/book-exploring-async-basics/1_concurrent_vs_parallel.html)
- [Async Basics - Async history](https://cfsamson.github.io/book-exploring-async-basics/2_async_history.html)
- [Async Basics - Strategies for handling I/O](https://cfsamson.github.io/book-exploring-async-basics/5_strategies_for_handling_io.html)
- [Async Basics - Epoll, Kqueue and IOCP](https://cfsamson.github.io/book-exploring-async-basics/6_epoll_kqueue_iocp.html)
Learning these concepts by studying futures is making it much harder than
it needs to be, so go on and read these chapters if you feel a bit unsure.
@@ -307,4 +307,3 @@ understanding of what the concerns are.
[tokio]: https://github.com/tokio-rs/tokio
[compat_info]: https://rust-lang.github.io/futures-rs/blog/2019/04/18/compatibility-layer.html
[futures_rs]: https://github.com/rust-lang/futures-rs

View File

@@ -581,7 +581,6 @@ by adding `std::marker::PhantomPinned` to your type on stable.
> guarantees you normally get from the compiler. An `unsafe` implementation can
> be perfectly safe to do, but you have no safety net.
### Projection/structural pinning
In short, projection is a programming language term. `mystruct.field1` is a

View File

@@ -44,7 +44,7 @@ The first thing an `executor` does when it gets a `Future` is polling it.
Rust provides a way for the Reactor and Executor to communicate through the `Waker`. The reactor stores this `Waker` and calls `Waker::wake()` on it once
a `Future` has resolved and should be polled again.
> Notice that this chapter has a bonus section called [A Proper Way to Park our Thread](./6_future_example.md#bonus-section---a-proper-way-to-park-our-thread) which shows how to avoid `thread::park`.
> Notice that this chapter has a bonus section called [A Proper Way to Park our Thread](./6_future_example.md#bonus-section---a-proper-way-to-park-our-thread) which shows how to avoid `thread::park`.
**Our Executor will look like this:**
@@ -55,7 +55,7 @@ fn block_on<F: Future>(mut future: F) -> F::Output {
// the first thing we do is to construct a `Waker` which we'll pass on to
// the `reactor` so it can wake us up when an event is ready.
let mywaker = Arc::new(MyWaker{ thread: thread::current() });
let waker = waker_into_waker(Arc::into_raw(mywaker));
let waker = mywaker_into_waker(Arc::into_raw(mywaker));
// The context struct is just a wrapper for a `Waker` object. Maybe in the
// future this will do more, but right now it's just a wrapper.
@@ -89,10 +89,10 @@ In all the examples you'll see in this chapter I've chosen to comment the code
extensively. I find it easier to follow along that way so I'll not repeat myself
here and focus only on some important aspects that might need further explanation.
It's worth noting that simply calling `thread::sleep` as we do here can lead to
It's worth noting that simply calling `thread::park` as we do here can lead to
both deadlocks and errors. We'll explain a bit more later and fix this if you
read all the way to the [Bonus Section](./6_future_example.md##bonus-section---a-proper-way-to-park-our-thread) at
the end of this chapter.
read all the way to the [Bonus Section](./6_future_example.md#bonus-section---a-proper-way-to-park-our-thread)
at the end of this chapter.
For now, we keep it as simple and easy to understand as we can by just going
to sleep.
@@ -104,10 +104,10 @@ exact same challenges as we do when borrowing across `yield` points.
> `Context` is just a wrapper around the `Waker`. At the time of writing this
book it's nothing more. In the future it might be possible that the `Context`
object will do more than just wrapping a `Future` so having this extra
object will do more than just wrapping a `Waker` so having this extra
abstraction gives some flexibility.
As explained in the [chapter about generators](./3_generators_pin.md), we use
As explained in the [chapter about Pin](./5_pin.md), we use
`Pin` and the guarantees that give us to allow `Future`s to have self
references.
@@ -175,7 +175,7 @@ const VTABLE: RawWakerVTable = unsafe {
// Instead of implementing this on the `MyWaker` object in `impl Mywaker...` we
// just use this pattern instead since it saves us some lines of code.
fn waker_into_waker(s: *const MyWaker) -> Waker {
fn mywaker_into_waker(s: *const MyWaker) -> Waker {
let raw_waker = RawWaker::new(s as *const (), &VTABLE);
unsafe { Waker::from_raw(raw_waker) }
}
@@ -299,7 +299,6 @@ To be able to run the code here in the browser there is not much real I/O we
can do so just pretend that this is actually represents some useful I/O operation
for the sake of this example.
**Our Reactor will look like this:**
```rust, noplaypen, ignore
@@ -494,7 +493,7 @@ fn main() {
# let mywaker = Arc::new(MyWaker {
# thread: thread::current(),
# });
# let waker = waker_into_waker(Arc::into_raw(mywaker));
# let waker = mywaker_into_waker(Arc::into_raw(mywaker));
# let mut cx = Context::from_waker(&waker);
#
# // SAFETY: we shadow `future` so it can't be accessed again.
@@ -542,7 +541,7 @@ fn main() {
# )
# };
#
# fn waker_into_waker(s: *const MyWaker) -> Waker {
# fn mywaker_into_waker(s: *const MyWaker) -> Waker {
# let raw_waker = RawWaker::new(s as *const (), &VTABLE);
# unsafe { Waker::from_raw(raw_waker) }
# }
@@ -735,7 +734,7 @@ Don't forget the exercises in the last chapter 😊.
## Bonus Section - a Proper Way to Park our Thread
As we explained earlier in our chapter, simply calling `thread::sleep` is not really
As we explained earlier in our chapter, simply calling `thread::park` is not really
sufficient to implement a proper reactor. You can also reach a tool like the `Parker`
in crossbeam: [crossbeam::sync::Parker][crossbeam_parker]

View File

@@ -209,9 +209,7 @@ impl Drop for Reactor {
## A little side note
The comments delimiting the Executor, `Future` implementation and Reactor,
emphasize on what is part of the language (Future and Waker) and what is not (runtime specifics).
The comments delimiting the Executor, `Future` implementation and Reactor,
emphasize on what is part of the language (Future and Waker) and what is not (runtime specifics).
Therefore, the comments associate the `Waker` with the `Future` implementation,
despite its strong relation with the Executor.

View File

@@ -76,7 +76,7 @@ linked to in the book, here are some of my suggestions:
[The Tokio Blog](https://tokio.rs/blog/2019-10-scheduler/)
[Stjepan's blog with a series where he implements an Executor](https://stjepang.github.io/)
[Stjepan's blog with a series where he implements an Executor](https://web.archive.org/web/20200207092849/https://stjepang.github.io/2020/01/31/build-your-own-executor.html)
[Jon Gjengset's video on The Why, What and How of Pinning in Rust](https://youtu.be/DkMwYxfSYNQ)
@@ -84,4 +84,4 @@ linked to in the book, here are some of my suggestions:
[condvar_std]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html
[condvar_wiki]: https://en.wikipedia.org/wiki/Monitor_(synchronization)#Condition_variables
[arcwake]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures/task/trait.ArcWake.html
[arcwake]: https://rust-lang-nursery.github.io/futures-api-docs/0.3.0-alpha.13/futures/task/trait.ArcWake.html

View File

@@ -16,13 +16,13 @@ topic of different types of executors and runtimes. We'll just implement a very
simple runtime in this book introducing some concepts but it's enough to get
started.
[Stjepan Glavina](https://github.com/stjepang) has made an excellent series of
articles about async runtimes and executors, and if the rumors are right there
is more to come from him in the near future.
[Stjepan Glavina](https://web.archive.org/web/20200812203230/https://github.com/stjepang)
has made an excellent series of articles about async runtimes and executors,
and if the rumors are right there is more to come from him in the near future.
The way you should go about it is to read this book first, then continue
reading the [articles from stjepang](https://stjepang.github.io/) to learn more
about runtimes and how they work, especially:
reading [Stjepan's articles](https://web.archive.org/web/20200610130514/https://stjepang.github.io/)
to learn more about runtimes and how they work, especially:
1. [Build your own block_on()](https://web.archive.org/web/20200511234503/https://stjepang.github.io/2020/01/25/build-your-own-block-on.html)
2. [Build your own executor](https://web.archive.org/web/20200207092849/https://stjepang.github.io/2020/01/31/build-your-own-executor.html)