Skip to content

Commit 392b6df

Browse files
committed
Copyedits for the book
1 parent f9fe739 commit 392b6df

18 files changed

+54
-53
lines changed

docs/src/concepts/futures.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ towards
4040
- Start doing X
4141
- Once X succeeds, start doing Y
4242

43-
Remember the talk about "deferred computation" in the intro? That's all it is. Instead of telling the computer what to execute and decide upon *now*, you tell it what to start doing and how to react on potential events the... well... `Future`.
43+
Remember the talk about "deferred computation" in the intro? That's all it is. Instead of telling the computer what to execute and decide upon *now*, you tell it what to start doing and how to react on potential events in the... well... `Future`.
4444

4545
[futures]: https://doc.rust-lang.org/std/future/trait.Future.html
4646

@@ -55,7 +55,7 @@ Let's have a look at a simple function, specifically the return value:
5555
contents
5656
}
5757

58-
You can call that at any time, so you are in full control on when you call it. But here's the problem: the moment you call it, you transfer control to the called function. It returns a value.
58+
You can call that at any time, so you are in full control of when you call it. But here's the problem: the moment you call it, you transfer control to the called function. It returns a value.
5959
Note that this return value talks about the past. The past has a drawback: all decisions have been made. It has an advantage: the outcome is visible. We can unwrap the presents of program past and then decide what to do with it.
6060

6161
But here's a problem: we wanted to abstract over *computation* to be allowed to let someone else choose how to run it. That's fundamentally incompatible with looking at the results of previous computation all the time. So, let's find a type that describes a computation without running it. Let's look at the function again:
@@ -84,8 +84,8 @@ Every call to `poll()` can result in one of these two cases:
8484
1. The future is done, `poll` will return [`Poll::Ready`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Ready)
8585
2. The future has not finished executing, it will return [`Poll::Pending`](https://doc.rust-lang.org/std/task/enum.Poll.html#variant.Pending)
8686

87-
This allows us to externally check if a `Future` has finished doing its work, or is finally done and can give us the value. The most simple way (but not efficient) would be to just constantly poll futures in a loop. There's optimisations here, and this is what a good runtime is does for you.
88-
Note that calling `poll` after case 1 happened may result in confusing behaviour. See the [futures-docs](https://doc.rust-lang.org/std/future/trait.Future.html) for details.
87+
This allows us to externally check if a `Future` has finished doing its work, or is finally done and can give us the value. The most simple way (but not efficient) would be to just constantly poll futures in a loop. There's optimisations here, and this is what a good runtime does for you.
88+
Note that calling `poll` after case 1 happened may result in confusing behaviour. See the [Future docs](https://doc.rust-lang.org/std/future/trait.Future.html) for details.
8989

9090
## Async
9191

@@ -121,3 +121,5 @@ A `Future` is any data type that does not represent a value, but the ability to
121121
Next, we will introduce you to `tasks`, which we need to actually *run* Futures.
122122

123123
[^1]: Two parties reading while it is guaranteed that no one is writing is always safe.
124+
125+
[futures]: https://rust-lang.github.io/async-book/02_execution/02_future.html

docs/src/concepts/tasks.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Now that we know what Futures are, we now want to run them!
44

5-
In `async-std`, the `tasks` (TODO: link) module is responsible for this. The simplest way is using the `block_on` function:
5+
In `async-std`, the [`tasks`](https://docs.rs/async-std/latest/async_std/task/index.html) module is responsible for this. The simplest way is using the `block_on` function:
66

77
```rust
88
use async_std::fs::File;
@@ -51,9 +51,9 @@ task::spawn(async { })
5151

5252
```
5353

54-
`spawn` takes a Future and starts running it on a `Task`. It returns a `JoinHandle`. Futures in Rust are sometimes called *cold* Futures. You need something that starts running them. To run a Future, there may be some additional bookkeeping required, e.g. if it's running or finished, where it is being placed in memory and what the current state is. This bookkeeping part is abstracted away in a `Task`. A `Task` is similar to a `Thread`, with some minor differences: it will be scheduled by the program instead of the operating system kernel and if it encounters a point where it needs to wait, the program itself responsible for waking it up again. We’ll talk a little bit about that later. An `async_std` task can also has a name and an ID, just like a thread.
54+
`spawn` takes a Future and starts running it on a `Task`. It returns a `JoinHandle`. Futures in Rust are sometimes called *cold* Futures. You need something that starts running them. To run a Future, there may be some additional bookkeeping required, e.g. if it's running or finished, where it is being placed in memory and what the current state is. This bookkeeping part is abstracted away in a `Task`. A `Task` is similar to a `Thread`, with some minor differences: it will be scheduled by the program instead of the operating system kernel and if it encounters a point where it needs to wait, the program itself is responsible for waking it up again. We’ll talk a little bit about that later. An `async_std` task can also have a name and an ID, just like a thread.
5555

56-
For now, it is enough to know that once you `spawn`ed a task, it will continue running in the background. The `JoinHandle` in itself is a future that will finish once the `Task` ran to conclusion. Much like with `threads` and the `join` function, we can now call `block_on` on the handle to *block* the program (or the calling thread, to be specific) to wait for it to finish.
56+
For now, it is enough to know that once you `spawn` a task, it will continue running in the background. The `JoinHandle` in itself is a future that will finish once the `Task` has run to conclusion. Much like with `threads` and the `join` function, we can now call `block_on` on the handle to *block* the program (or the calling thread, to be specific) to wait for it to finish.
5757

5858
## Tasks in `async_std`
5959

@@ -64,11 +64,11 @@ Tasks in `async_std` are one of the core abstractions. Much like Rust’s `threa
6464
- The carry desirable metadata for debugging
6565
- They support task local storage
6666

67-
`async_std`s task api handles setup and teardown of a backing runtime for you and doesn’t rely on a runtime being started.
67+
`async_std`'s task API handles setup and teardown of a backing runtime for you and doesn’t rely on a runtime being started.
6868

6969
## Blocking
7070

71-
`Task`s are assumed to run _concurrently_, potentially by sharing a thread of execution. This means that operations blocking an _operating system thread_, such as `std::thread::sleep` or io function from Rusts stdlib will _stop execution of all tasks sharing this thread_. Other libraries (such as database drivers) have similar behaviour. Note that _blocking the current thread_ is not in and by itself bad behaviour, just something that does not mix well with they concurrent execution model of `async-std`. Essentially, never do this:
71+
`Task`s are assumed to run _concurrently_, potentially by sharing a thread of execution. This means that operations blocking an _operating system thread_, such as `std::thread::sleep` or I/O function from Rust's stdlib will _stop execution of all tasks sharing this thread_. Other libraries (such as database drivers) have similar behaviour. Note that _blocking the current thread_ is not in and of itself bad behaviour, just something that does not mix well with the concurrent execution model of `async-std`. Essentially, never do this:
7272

7373
```rust
7474
fn main() {
@@ -83,7 +83,7 @@ If you want to mix operation kinds, consider putting such operations on a `threa
8383

8484
## Errors and panics
8585

86-
`Task`s report errors through normal channels: If they are fallible, their `Output` should be of kind `Result<T,E>`.
86+
`Task`s report errors through normal channels: If they are fallible, their `Output` should be of the kind `Result<T,E>`.
8787

8888
In case of `panic`, behaviour differs depending on if there's a reasonable part that addresses the `panic`. If not, the program _aborts_.
8989

@@ -102,7 +102,7 @@ thread 'async-task-driver' panicked at 'test', examples/panic.rs:8:9
102102
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
103103
```
104104

105-
While panicing a spawned tasks will abort:
105+
While panicing a spawned task will abort:
106106

107107
```rust
108108
task::spawn(async {

docs/src/glossary.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
### blocking
44

5-
"blocked" generally refers to conditions that keep a task from doing its work. For example, it might need data to be sent by a client before continuing. When tasks becomes blocked, usually, other tasks are scheduled.
5+
"blocked" generally refers to conditions that keep a task from doing its work. For example, it might need data to be sent by a client before continuing. When tasks become blocked, usually, other tasks are scheduled.
66

7-
Sometimes you hear that you should never call "blocking functions" in an async context. What this refers to is functions that block the current thread and do not yield control back. This keeps the executor from using this thread to schedule another task.
7+
Sometimes you hear that you should never call "blocking functions" in an async context. What this refers to is functions that block the current thread and do not yield control back. This keeps the executor from using this thread to schedule another task.

docs/src/introduction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
![async-std logo](./images/horizontal_color.svg)
44

5-
This book serves as high-level documentation for `async-std` and a way of learning async programming in Rust through it. As such, it focusses on the `async-std` API and the task model it gives you.
5+
This book serves as high-level documentation for `async-std` and a way of learning async programming in Rust through it. As such, it focuses on the `async-std` API and the task model it gives you.
66

77
Please note that the Rust project provides its own book on asynchronous programming, called ["Asynchronous Programming in Rust"][async-book], which we highly recommend reading along with this book, as it provides a different, wider view on the topic.
88

docs/src/overview/async-std.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Welcome to `async-std`
22

3-
`async-std` along with its [supporting libraries][organization] is a library making your life in async programming easier. It provides provide fundamental implementations for downstream libraries and applications alike. The name reflects the approach of this library: it is a closely modeled to the Rust main standard library as possible, replacing all components by async counterparts.
3+
`async-std`, along with its [supporting libraries][organization], is a library making your life in async programming easier. It provides fundamental implementations for downstream libraries and applications alike. The name reflects the approach of this library: it is as closely modeled to the Rust main standard library as possible, replacing all components by async counterparts.
44

5-
`async-std` provides an interface to all important primitives: filesystem operations, network operations and concurrency basics like timers. It also exposes an `task` in a model similar to the `thread` module found in the Rust standard lib. But it does not only include io primitives, but also `async/await` compatible versions of primitives like `Mutex`. You can read more about `async-std` in [the overview chapter][overview-std].
5+
`async-std` provides an interface to all important primitives: filesystem operations, network operations and concurrency basics like timers. It also exposes a `task` in a model similar to the `thread` module found in the Rust standard lib. But it does not only include I/O primitives, but also `async/await` compatible versions of primitives like `Mutex`. You can read more about `async-std` in [the overview chapter][overview-std].
66

77
[organization]: https://github.com/async-rs/async-std
88
[overview-std]: overview/async-std/

docs/src/overview/stability-guarantees.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,6 @@ Security fixes will be applied to _all_ minor branches of this library in all _s
3535

3636
## Credits
3737

38-
This policy is based on [burntsushis regex crate][regex-policy].
38+
This policy is based on [BurntSushi's regex crate][regex-policy].
3939

4040
[regex-policy]: https://github.com/rust-lang/regex#minimum-rust-version-policy

docs/src/overview/std-and-library-futures.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ The future defined in the [futures-rs](https://docs.rs/futures-preview/0.3.0-alp
1010

1111
It is critical to understand the difference between `std::future::Future` and `futures::future::Future`, and the approach that `async-std` takes towards them. In itself, `std::future::Future` is not something you want to interact with as a user—except by calling `.await` on it. The inner workings of `std::future::Future` are mostly of interest to people implementing `Future`. Make no mistake—this is very useful! Most of the functionality that used to be defined on `Future` itself has been moved to an extension trait called [`FuturesExt`](https://docs.rs/futures-preview/0.3.0-alpha.17/futures/future/trait.FutureExt.html). From this information, you might be able to infer that the `futures` library serves as an extension to the core Rust async features.
1212

13-
In the same tradition as `futures`, `async-std` re-exports the core `std::future::Future` type. You can get actively opt into the extensions provided by the `futures-preview` crate by adding it your `Cargo.toml` and importing `FuturesExt`.
13+
In the same tradition as `futures`, `async-std` re-exports the core `std::future::Future` type. You can actively opt into the extensions provided by the `futures-preview` crate by adding it to your `Cargo.toml` and importing `FuturesExt`.
1414

1515
## Interfaces and Stability
1616

1717
`async-std` aims to be a stable and reliable library, at the level of the Rust standard library. This also means that we don't rely on the `futures` library for our interface. Yet, we appreciate that many users have come to like the conveniences that `futures-rs` brings. For that reason, `async-std` implements all `futures` traits for its types.
1818

19-
Luckily, the approach from above gives you full flexibility. If you care about stability a lot, you can just use `async-std` as is. If you prefer the `futures` library interfaces, you link those in.. Both uses are first class.
19+
Luckily, the approach from above gives you full flexibility. If you care about stability a lot, you can just use `async-std` as is. If you prefer the `futures` library interfaces, you link those in. Both uses are first class.
2020

2121
## `async_std::future`
2222

docs/src/tutorial/accept_loop.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>
2121

2222
1. `async_std` uses `std` types where appropriate.
2323
We'll need `ToSocketAddrs` to specify address to listen on.
24-
2. `prelude` re-exports some traits required to work with futures and streams
25-
3. The `task` module roughtly corresponds to `std::thread` module, but tasks are much lighter weight.
24+
2. `prelude` re-exports some traits required to work with futures and streams.
25+
3. The `task` module roughly corresponds to the `std::thread` module, but tasks are much lighter weight.
2626
A single thread can run many tasks.
2727
4. For the socket type, we use `TcpListener` from `async_std`, which is just like `std::net::TcpListener`, but is non-blocking and uses `async` API.
2828
5. We will skip implementing comprehensive error handling in this example.
@@ -43,7 +43,7 @@ async fn server(addr: impl ToSocketAddrs) -> Result<()> { // 1
4343
}
4444
```
4545

46-
1. We mark `server` function as `async`, which allows us to use `.await` syntax inside.
46+
1. We mark the `server` function as `async`, which allows us to use `.await` syntax inside.
4747
2. `TcpListener::bind` call returns a future, which we `.await` to extract the `Result`, and then `?` to get a `TcpListener`.
4848
Note how `.await` and `?` work nicely together.
4949
This is exactly how `std::net::TcpListener` works, but with `.await` added.
@@ -73,4 +73,4 @@ The crucial thing to realise that is in Rust, unlike other languages, calling an
7373
Async functions only construct futures, which are inert state machines.
7474
To start stepping through the future state-machine in an async function, you should use `.await`.
7575
In a non-async function, a way to execute a future is to handle it to the executor.
76-
In this case, we use `task::block_on` to execute future on the current thread and block until it's done.
76+
In this case, we use `task::block_on` to execute a future on the current thread and block until it's done.

docs/src/tutorial/all_together.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
## All Together
33

4-
At this point, we only need to start broker to get a fully-functioning (in the happy case!) chat:
4+
At this point, we only need to start the broker to get a fully-functioning (in the happy case!) chat:
55

66
```rust
77
#![feature(async_await)]
@@ -129,7 +129,7 @@ async fn broker(mut events: Receiver<Event>) -> Result<()> {
129129
}
130130
```
131131

132-
1. Inside the `server`, we create broker's channel and `task`.
132+
1. Inside the `server`, we create the broker's channel and `task`.
133133
2. Inside `client`, we need to wrap `TcpStream` into an `Arc`, to be able to share it with the `client_writer`.
134134
3. On login, we notify the broker.
135135
Note that we `.unwrap` on send: broker should outlive all the clients and if that's not the case the broker probably panicked, so we can escalate the panic as well.

docs/src/tutorial/clean_shutdown.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## Clean Shutdown
22

3-
On of the problems of the current implementation is that it doesn't handle graceful shutdown.
3+
One of the problems of the current implementation is that it doesn't handle graceful shutdown.
44
If we break from the accept loop for some reason, all in-flight tasks are just dropped on the floor.
55
A more correct shutdown sequence would be:
66

@@ -10,7 +10,7 @@ A more correct shutdown sequence would be:
1010

1111
A clean shutdown in a channel based architecture is easy, although it can appear a magic trick at first.
1212
In Rust, receiver side of a channel is closed as soon as all senders are dropped.
13-
That is, as soon as producers exit and drop their senders, the rest of the system shutdowns naturally.
13+
That is, as soon as producers exit and drop their senders, the rest of the system shuts down naturally.
1414
In `async_std` this translates to two rules:
1515

1616
1. Make sure that channels form an acyclic graph.
@@ -83,4 +83,4 @@ Notice what happens with all of the channels once we exit the accept loop:
8383
3. It's crucial that, at this stage, we drop the `peers` map.
8484
This drops writer's senders.
8585
4. Now we can join all of the writers.
86-
5. Finally, we join the broker, which also guarantees that all the writes have terminated.
86+
5. Finally, we join the broker, which also guarantees that all the writes have terminated.

0 commit comments

Comments
 (0)