I have been interested in asynchronous programming (synchronous realization of asynchronous functions) since I got to know Go. Google learned that Rust also supports asynchronous programming. The main asynchronous programming libraries in Rust are Tokio and Async-STD. After scanning the document, the syntax is very similar. Tokio has long supported asynchronous programming features and is constantly iterating, and there are a number of frameworks that use Tokio. Async-std version 1.0 was released on September 26, 2019 and is very young. After reviewing some resources, the async-STD library was selected as the primary learning library for Rust asynchronous programming. The reason is simple:
- Claims to be compliant with standard libraries,
tokio
Subsequent versions also lean in this direction - There is no
tokio
Historical baggage allows faster iteration of new features - than
tokio
Libraries are smaller and more powerful
Here’s an official example:
extern crate async_std;
use async_std::{fs::File, io, io::prelude::*, task};
async fn read_file(path: &str) -> io::Result<String> {
let mutfile = File::open(path).await? ;let mut contents = String::new();
file.read_to_string(&mutcontents).await? ;Ok(contents)
}
fn main() {
let reader_task = task::spawn(async {
let result = read_file("./src/main.rs").await;
match result {
Ok(s) => println!("{}", s),
Err(e) => println!("Error reading file: {:? }", e)
}
});
task::block_on(reader_task);
}
Copy the code
The main function of this example is to read the contents of the file and output to standard output. Asynchrony is embodied in:
- Open files that are blocked voluntarily yield threads.
File::open(path).await?
- Read the contents of the file, blocking will also voluntarily free up the thread.
file.read_to_string(&mut contents).await?
The core keywords of Rust asynchronous programming include:
- Async: Builds one
Future
The structure of the - .await: by waiting
Future
return
Take a look at Future:
pub trait Future {
type Output;
fn poll(self: Pin<&mut Self>, cx: &mutContext) -> Poll<Self::Output>; . }Copy the code
The core function is poll, which checks whether the Future can be returned. This function should not contain blocking function calls, but rather check the state of the task (a task is a block of code or function that needs to be executed). The return value of the function:
- Poll: : Pending:
future
Not ready - Poll: : Ready (val) :
future
Ready,val
The value istask
The return value of.
If the future is not ready, the task needs to be put into the run-time system again for scheduling. Through the Walker function of the Context variable.
pub struct Context<'a> {
waker: &'a Waker,
...
}
impl<'a> Context<'a> {
pub fn waker(&self) - > &'a Waker {
&self.waker
}
...
}
Copy the code
The whole process of asynC-STD asynchronous call is as follows:
- through
async
Key constructionfuture
structure - through
.await
或task::spawn
And so onfuture
Structure associated functions or code blocks wrapped intotask
Into theRun-time system
schedule - Wait for the event to trigger. Such as socket read and write, file read and write, timer, signal, lock and so on
- Associated with scheduling events
task
, and thefuture
Check the return value of the structure. If it isReady
, returns the result, and the original execution flow continues; Otherwise, callContext
thewaker
Function willtask
Once again into theRun-time system
Schedule and wait for the next event to trigger.
reference
-
async-std
-
Future