mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 22:37:49 +00:00
Remove old section
This commit is contained in:
@@ -488,97 +488,9 @@ Note that this function does not start the execution of the state machine. This
|
|||||||
|
|
||||||
### Pinning
|
### Pinning
|
||||||
|
|
||||||
|
### Executors
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### The Async Keyword
|
|
||||||
|
|
||||||
The purpose of the async/await pattern is to make working with futures easier. Rust has language-level support for this pattern built on the two keywords `async` and `await`. We will explain them individually, starting with `async`.
|
|
||||||
|
|
||||||
The purpose of the `async` keyword is to turn a synchronous function into an asynchronous function that returns a `Future`:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
fn synchronous() -> u32 {
|
|
||||||
42
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn asynchronous() -> u32 {
|
|
||||||
42
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
While both functions specify a return type of `u32`, the `async` keyword turns the return type of the second function into `impl Future<Output = u32>`. So instead of returning an `u32` directly, the `asynchronous` function returns a type that implements the `Future` trait with output type `u32`. We can see this when we try to assign the result to a variable of type `u32`:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let val: u32 = asynchronous();
|
|
||||||
```
|
|
||||||
|
|
||||||
The compiler responds with the following error ([try it on the playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=590273d2f4ef75eb890c5354f788e29c)):
|
|
||||||
|
|
||||||
```
|
|
||||||
error[E0308]: mismatched types
|
|
||||||
--> src/main.rs:3:23
|
|
||||||
|
|
|
||||||
3 | let val: u32 = asynchronous();
|
|
||||||
| --- ^^^^^^^^^^^^^^ expected `u32`, found opaque type
|
|
||||||
| |
|
|
||||||
| expected due to this
|
|
||||||
...
|
|
||||||
10 | async fn asynchronous() -> u32 {
|
|
||||||
| --- the `Output` of this `async fn`'s found opaque type
|
|
||||||
|
|
|
||||||
= note: expected type `u32`
|
|
||||||
found opaque type `impl std::future::Future`
|
|
||||||
```
|
|
||||||
|
|
||||||
The relevant part of that error message are the last two lines: It expects an `u32` because of the type annotation, but the function returned an implementation of the `Future` trait instead.
|
|
||||||
|
|
||||||
Of course, changing the return type alone would not work. Instead, the compiler also needs to convert the function body, which is `42` in our case, into a future. Since `42` is not asynchronous, the compiler just generates a future that returns the result on the first `poll`. The generated code _could_ look something like this:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
struct GeneratedFuture;
|
|
||||||
|
|
||||||
impl Future for GeneratedFuture {
|
|
||||||
type Output = u32;
|
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
|
|
||||||
Poll::Ready(42)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn asynchronous() -> impl Future<Output = u32> {
|
|
||||||
GeneratedFuture
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Instead of returning `u32`, the `asynchronous` function now returns an instance of a new `GeneratedFuture` struct. This struct implements the `Future` trait by returning `Poll::Ready(42)` on `poll`. The `42` is the body of `asynchronous` in this case.
|
|
||||||
|
|
||||||
Note that this is just an example implementation. The actual code generated by the compiler uses a much more powerful approach, which we will explain in a moment.
|
|
||||||
|
|
||||||
In addition to `async` futures, Rust also supports `async` blocks:
|
|
||||||
|
|
||||||
```rust
|
|
||||||
let future = async {
|
|
||||||
42
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
The `future` variable also has the type `impl Future<Output = u32>` in this case. The generated code is very similar to the `async fn`, only without a function call: `let future = GeneratedFuture;`.
|
|
||||||
|
|
||||||
We now know roughly what the `async` keyword does, but we still don't know why it's useful yet. After all, there is no advantage of returning a `impl Future<Output = u32>` instead of returning the `u32` directly. To answer this question, we have to explore different ways to work with futures.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### Await
|
|
||||||
|
|
||||||
### Generators
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user