-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NOTE: `mdbook test` does not allow code samples to reference other crates, so they must be marked as `compile_fail`; see #175.
- Loading branch information
Showing
4 changed files
with
77 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
# Futures | ||
|
||
What is the type of an async operation? | ||
|
||
```rust,editable,compile_fail | ||
use tokio::time; | ||
async fn count_to(count: i32) -> i32 { | ||
for i in 1..=count { | ||
println!("Count in task: {i}!"); | ||
time::sleep(time::Duration::from_millis(5)).await; | ||
} | ||
count | ||
} | ||
#[tokio::main] | ||
async fn main() { | ||
let _: () = count_to(13); | ||
} | ||
``` | ||
|
||
[Future](https://doc.rust-lang.org/nightly/src/core/future/future.rs.html#37) | ||
is a trait, implemented by objects that represent an operation that may not be | ||
complete yet. A future can be polled, and `poll` returns either | ||
`Poll::Ready(result)` or `Poll::Pending`. | ||
|
||
```rust | ||
use std::pin::Pin; | ||
use std::task::Context; | ||
|
||
pub trait Future { | ||
type Output; | ||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>; | ||
} | ||
|
||
pub enum Poll<T> { | ||
Ready(T), | ||
Pending, | ||
} | ||
``` | ||
|
||
An async function returns an `impl Future`, and an async block evaluates to an | ||
`impl Future`. It's also possible (but uncommon) to implement `Future` for your | ||
own types. For example, the `JoinHandle` returned from `tokio::spawn` implements | ||
`Future` to allow joining to it. | ||
|
||
The `.await` keyword, applied to a Future, causes the current async function or | ||
block to pause until that Future is ready, and then evaluates to its output. | ||
|
||
An important difference from other languages is that a Future is inert: it does | ||
not do anything until it is polled. | ||
|
||
<details> | ||
|
||
* Run the example and look at the error message. `_: () = ..` is a common | ||
technique for getting the type of an expression. Try adding a `.await` in | ||
`main`. | ||
|
||
* The `Future` and `Poll` types are conceptually quite simple, and implemented as | ||
such in `std::task`. | ||
|
||
* We will not get to `Pin` and `Context`, as we will focus on writing async | ||
code, rather than building new async primitives. Briefly: | ||
|
||
* `Context` allows a Future to schedule itself to be polled again when an | ||
event occurs. | ||
|
||
* `Pin` ensures that the Future isn't moved in memory, so that pointers into | ||
that future remain valid. This is required to allow references to remain | ||
valid after an `.await`. | ||
|
||
</details> |