There are many concepts involved in future. Future can be used as a task with multiple strings, and then many tasks will be sent to the thread pool. When the thread is executing, it will block in the block_ The on () call waits for an event. For example, the epoll event will drive the nearest Future::poll(), and then execute the next level of Future::poll(), and finally return the value.
There are many pits in Rust Future, and there are differences between the earlier version and nightly version. Like earlier versions
Future<Item=i32, Error=Error>
Later, it was changed to writing method:
Future<Output=Result<i32,Error>>
Here are three ways of writing. In fact, they are all grammar sugar, which will turn into the most troublesome one in the end!
use futures::future::Future; use futures::task::{Poll, Context}; use futures::future::{ok, err, join}; use std::error::Error; use std::result::Result; use std::pin::Pin; // The most convenient way to write async fn fn1() -> i32 { 111 } fn fn2() -> impl Future<Output = u32> { async { 222 } } struct Foo { name: &'static str, age:i32, } impl Future for Foo { type Output = i32; fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { println!("peding..., self.age: {}", self.age); Poll::Ready(self.age) // If you keep returning to Pending, you will always be stuck here //Poll::Pending } } fn fn3() -> Foo { Foo{name:"aaa", age:333} } fn main() { let f1 = futures::executor::block_on(fn1()); println!("f1: {}", f1); let f2 = futures::executor::block_on(fn2()); println!("f2: {}", f2); let foo = Foo{name:"abc", age:2222}; let f3 = futures::executor::block_on(foo); println!("f3: {}", f3); }
If the main() function is to use. await, it will be changed to Future. You need to use the macro to convert the following writing method:
#[tokio::main] async main() { let f1 = fn1().await; let f2 = fn2().await; }
Will be converted to:
futures::executor::block_on(async { main() { let f1 = fn1().await; let f2 = fn2().await; } })