Select
select 操作は、複数の future のうちいずれか 1 つの準備ができるまで待機し、その future の結果に応じて処理を行います。JavaScript では、これは Promise.race に 似ています。Python では、 asyncio.wait(task_set, return_when=asyncio.FIRST_COMPLETED) に相当します。
match 文と同様に、select! の本体には複数のアームがあり、それぞれ pattern = future => statement という形式を取ります。future の準備ができると、 その戻り値は pattern によって分解されます。続いて、得られた変数を使って statement が実行されます。statement の結果が select! マクロの結果になります。
// 著作権 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 use tokio::sync::mpsc; use tokio::time::{Duration, sleep}; #[tokio::main] async fn main() { let (tx, mut rx) = mpsc::channel(32); let listener = tokio::spawn(async move { tokio::select! { Some(msg) = rx.recv() => println!("got: {msg}"), _ = sleep(Duration::from_millis(50)) => println!("timeout"), }; }); sleep(Duration::from_millis(10)).await; tx.send(String::from("Hello!")).await.expect("Failed to send greeting"); listener.await.expect("Listener failed"); }
-
ここでの
listenerasync ブロックは一般的な形です。何らかの async イベント、 またはタイムアウトを待ちます。sleepをより長くして、失敗することを確認して ください。この状況でsendも失敗するのはなぜでしょうか? -
「アクター」アーキテクチャでは、
select!はループ内でもよく使われます。そこでは タスクがループ内でイベントに反応します。これにはいくつかの落とし穴があり、 それについては次のセグメントで説明します。