Executing Multiple Futures at a Time
複数の非同期関数を並行処理する方法の例
join!
join!が返す値は、各Future結果のタプル。1
FutureがResultを返す場合、try_join!がよいらしい。
example
検証時のsleepとして、std::thread::sleepは同期的にブロックしてしまうため、非同期用のsleepが必要。2
tokio::time::sleepを使用した例
use std::time::Duration; async fn dance1() { println!("dance1."); tokio::time::sleep(Duration::from_secs(10)).await; println!("dance1."); } async fn dance2() { println!("dance2."); tokio::time::sleep(Duration::from_secs(1)).await; } async fn dance3() { println!("dance3."); tokio::time::sleep(Duration::from_secs(1)).await; } #[tokio::main] async fn main() { tokio::join!(dance1(), dance2(), dance3()); }
std::thread::sleepを使用した失敗例futures::jointokio::join
色々なjoin
色々なjoinがある。差分は不明。対応するランタイムが違うだけならよいが。
source code
select!
基本
複数の非同期処理のうち一つが完了すれば、応じた処理をする。
他の非同期処理の完了は待たない。例えば副作用関数や不純関数の場合はどういう扱いになるのだろうか?
select!も式なのでそれぞれの返り値は同じ型でなければならない。
syntax: <pattern> = <expression> => <code>,
select!に渡すFutureはUnpinとfutures::future::FusedFutureを実装する必要がある3
Unpinはselectが可変参照を取得するために必要。moveしては後続処理ができないらしい。
FusedFutureはselectが完了した後にpollしないように必要。FusedFutureは互いに完了したかどうかを追跡する。selectループで完了していないFutureのみpollするために必要。
future::readyによって変えるFutureはFusedFutureを実装しているので、再度pollされないような仕組み。
futures::select- Rust Playground
- TODO: なぜ結果が一つに収束するのだろうか
tokio::select
Streamはfutures::stream::FusedStreamに対応している。
Concurrent tasks in a select loop
futures::future::Fuse::terminatedは既に完了したFutureをFuseできるので、selectループで便利らしい。
source code
Spawning
spawnはJoinHandleを返す。
JoinHandleはFutureを実装しているのでawaitするまで結果を得られない。4
mainタスクとspawnされたタスクとのやり取りとして、channelsを利用する。
join! - Asynchronous Programming in Rust
The value returned by join! is a tuple containing the output of each Future passed in.
rust - Concurrent async/await with sleep - Stack Overflow
Since the standard/original thread::sleep is blocking, it turns out that the async library is providing async_std::task::sleep( ... ) which is the nonblocking version for sleep.
select in futures - Rust
Futures directly passed to select! must be Unpin and implement FusedFuture.
Spawning - Asynchronous Programming in Rust
The JoinHandle returned by spawn implements the Future trait, so we can .await it to get the result of the task.