Put plural endings after grave accents

This commit is contained in:
olehmisar
2020-04-08 13:53:35 +03:00
parent a3ac3071df
commit 8dfc2f8ed3
7 changed files with 175 additions and 175 deletions

View File

@@ -1,6 +1,6 @@
# Futures in Rust
We'll create our own `Futures` together with a fake reactor and a simple
We'll create our own `Future`s together with a fake reactor and a simple
executor which allows you to edit, run an play around with the code right here
in your browser.
@@ -51,8 +51,8 @@ a `Future` has resolved and should be polled again.
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() });
// 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));
// The context struct is just a wrapper for a `Waker` object. Maybe in the
@@ -70,7 +70,7 @@ fn block_on<F: Future>(mut future: F) -> F::Output {
// an event occurs, or a thread has a "spurious wakeup" (an unexpected wakeup
// that can happen for no good reason).
let val = loop {
match Future::poll(pinned, &mut cx) {
// when the Future is ready we're finished
@@ -88,26 +88,26 @@ 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.
Now that you've read so much about `Generators` and `Pin` already this should
Now that you've read so much about `Generator`s and `Pin` already this should
be rather easy to understand. `Future` is a state machine, every `await` point
is a `yield` point. We could borrow data across `await` points and we meet the
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 `Future` so having this extra
abstraction gives some flexibility.
As explained in the [chapter about generators](./3_generators_pin.md), we use
`Pin` and the guarantees that give us to allow `Futures` to have self
`Pin` and the guarantees that give us to allow `Future`s to have self
references.
## The `Future` implementation
Futures has a well defined interface, which means they can be used across the
entire ecosystem.
entire ecosystem.
We can chain these `Futures` so that once a **leaf-future** is
We can chain these `Future`s so that once a **leaf-future** is
ready we'll perform a set of operations until either the task is finished or we
reach yet another **leaf-future** which we'll wait for and yield control to the
scheduler.
@@ -230,9 +230,9 @@ is just increasing the refcount in this case.
Dropping a `Waker` is as easy as decreasing the refcount. Now, in special
cases we could choose to not use an `Arc`. So this low-level method is there
to allow such cases.
to allow such cases.
Indeed, if we only used `Arc` there is no reason for us to go through all the
Indeed, if we only used `Arc` there is no reason for us to go through all the
trouble of creating our own `vtable` and a `RawWaker`. We could just implement
a normal trait.
@@ -245,13 +245,13 @@ The reactor will often be a global resource which let's us register interests
without passing around a reference.
> ### Why using thread park/unpark is a bad idea for a library
>
>
> It could deadlock easily since anyone could get a handle to the `executor thread`
> and call park/unpark on it.
>
>
> 1. A future could call `unpark` on the executor thread from a different thread
> 2. Our `executor` thinks that data is ready and wakes up and polls the future
> 3. The future is not ready yet when polled, but at that exact same time the
> 3. The future is not ready yet when polled, but at that exact same time the
> `Reactor` gets an event and calls `wake()` which also unparks our thread.
> 4. This could happen before we go to sleep again since these processes
> run in parallel.
@@ -277,13 +277,13 @@ Since concurrency mostly makes sense when interacting with the outside world (or
at least some peripheral), we need something to actually abstract over this
interaction in an asynchronous way.
This is the `Reactors` job. Most often you'll see reactors in Rust use a library
This is the `Reactor`s job. Most often you'll see reactors in Rust use a library
called [Mio][mio], which provides non blocking APIs and event notification for
several platforms.
The reactor will typically give you something like a `TcpStream` (or any other
resource) which you'll use to create an I/O request. What you get in return is a
`Future`.
`Future`.
>If our reactor did some real I/O work our `Task` in would instead be represent
>a non-blocking `TcpStream` which registers interest with the global `Reactor`.
@@ -434,7 +434,7 @@ which you can edit and change the way you like.
# task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
# thread::{self, JoinHandle}, time::{Duration, Instant}
# };
#
#
fn main() {
// This is just to make it easier for us to see when our Future was resolved
let start = Instant::now();
@@ -442,10 +442,10 @@ fn main() {
// Many runtimes create a glocal `reactor` we pass it as an argument
let reactor = Reactor::new();
// Since we'll share this between threads we wrap it in a
// Since we'll share this between threads we wrap it in a
// atmically-refcounted- mutex.
let reactor = Arc::new(Mutex::new(reactor));
// We create two tasks:
// - first parameter is the `reactor`
// - the second is a timeout in seconds
@@ -485,7 +485,7 @@ fn main() {
# // ============================= EXECUTOR ====================================
# fn block_on<F: Future>(mut future: F) -> F::Output {
# let mywaker = Arc::new(MyWaker{ thread: thread::current() });
# let mywaker = Arc::new(MyWaker{ thread: thread::current() });
# let waker = waker_into_waker(Arc::into_raw(mywaker));
# let mut cx = Context::from_waker(&waker);
# let val = loop {
@@ -497,13 +497,13 @@ fn main() {
# };
# val
# }
#
#
# // ====================== FUTURE IMPLEMENTATION ==============================
# #[derive(Clone)]
# struct MyWaker {
# thread: thread::Thread,
# }
#
#
# #[derive(Clone)]
# pub struct Task {
# id: usize,
@@ -511,19 +511,19 @@ fn main() {
# data: u64,
# is_registered: bool,
# }
#
#
# fn mywaker_wake(s: &MyWaker) {
# let waker_ptr: *const MyWaker = s;
# let waker_arc = unsafe {Arc::from_raw(waker_ptr)};
# waker_arc.thread.unpark();
# }
#
#
# fn mywaker_clone(s: &MyWaker) -> RawWaker {
# let arc = unsafe { Arc::from_raw(s).clone() };
# std::mem::forget(arc.clone()); // increase ref count
# RawWaker::new(Arc::into_raw(arc) as *const (), &VTABLE)
# }
#
#
# const VTABLE: RawWakerVTable = unsafe {
# RawWakerVTable::new(
# |s| mywaker_clone(&*(s as *const MyWaker)), // clone
@@ -532,12 +532,12 @@ fn main() {
# |s| drop(Arc::from_raw(s as *const MyWaker)), // decrease refcount
# )
# };
#
#
# fn waker_into_waker(s: *const MyWaker) -> Waker {
# let raw_waker = RawWaker::new(s as *const (), &VTABLE);
# unsafe { Waker::from_raw(raw_waker) }
# }
#
#
# impl Task {
# fn new(reactor: Arc<Mutex<Reactor>>, data: u64, id: usize) -> Self {
# Task {
@@ -548,7 +548,7 @@ fn main() {
# }
# }
# }
#
#
# impl Future for Task {
# type Output = usize;
# fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
@@ -565,7 +565,7 @@ fn main() {
# }
# }
# }
#
#
# // =============================== REACTOR ===================================
# struct Reactor {
# dispatcher: Sender<Event>,
@@ -577,7 +577,7 @@ fn main() {
# Close,
# Timeout(Waker, u64, usize),
# }
#
#
# impl Reactor {
# fn new() -> Self {
# let (tx, rx) = channel::<Event>();
@@ -597,34 +597,34 @@ fn main() {
# rl_clone.lock().map(|mut rl| rl.push(id)).unwrap();
# waker.wake();
# });
#
#
# handles.push(event_handle);
# }
# }
# }
#
#
# for handle in handles {
# handle.join().unwrap();
# }
# });
#
#
# Reactor {
# readylist,
# dispatcher: tx,
# handle: Some(handle),
# }
# }
#
#
# fn register(&mut self, duration: u64, waker: Waker, data: usize) {
# self.dispatcher
# .send(Event::Timeout(waker, duration, data))
# .unwrap();
# }
#
#
# fn close(&mut self) {
# self.dispatcher.send(Event::Close).unwrap();
# }
#
#
# fn is_ready(&self, id_to_check: usize) -> bool {
# self.readylist
# .lock()
@@ -632,7 +632,7 @@ fn main() {
# .unwrap()
# }
# }
#
#
# impl Drop for Reactor {
# fn drop(&mut self) {
# self.handle.take().map(|h| h.join().unwrap()).unwrap();
@@ -654,7 +654,7 @@ 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
`Future`.
These `Futures` are rather simple. Imagine our generator from a few chapters
These `Future`s 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, we yield the result of calling `poll` on
@@ -675,7 +675,7 @@ Future got 1 at time: 1.00.
Future got 2 at time: 3.00.
```
If these `Futures` were executed asynchronously we would expect to see:
If these `Future`s were executed asynchronously we would expect to see:
```ignore
Future got 1 at time: 1.00.
@@ -697,7 +697,7 @@ how they implement different ways of running Futures to completion.
[If I were you I would read this next, and try to implement it for our example.](./conclusion.md#building-a-better-exectuor).
That's actually it for now. There as probably much more to learn, this is enough
for today.
for today.
I hope exploring Futures and async in general gets easier after this read and I
do really hope that you do continue to explore further.
@@ -710,4 +710,4 @@ Don't forget the exercises in the last chapter 😊.
[playground_example]:https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=ca43dba55c6e3838c5494de45875677f
[spurious_wakeup]: https://cfsamson.github.io/book-exploring-async-basics/9_3_http_module.html#bonus-section
[condvar]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html
[crossbeam_parker]: https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html
[crossbeam_parker]: https://docs.rs/crossbeam/0.7.3/crossbeam/sync/struct.Parker.html