Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Async Runtime

ノンブロッキングコードを実行する前に、それを管理し、どのタスクを実行するか、 いつ実行するか、そして待機中に何をするかを決定する何かが必要です。その管理役はランタイムと呼ばれます。

これをコールセンターのコーディネーターのようなものだと考えてください。1 人の担当者が 折り返しの電話を待って手持ち無沙汰になる代わりに、コーディネーターは、ほかの担当者が待っている間に新しい仕事を割り当てることで、全員が忙しく動けるようにします。

Tokio は Rust におけるそのランタイムです。これがなければ、async 関数と .await はそれ自体では何もしません。

マクロ

tokio-badge

Tokio ランタイムを開始する最も簡単な方法は、tokio::main マクロを使うことです。これを main 関数の上に置くと、ランタイムの起動、コードの実行、そして完了時のシャットダウンまで、 すべてを処理してくれます。また、main を非ブロッキングにできるため、その中で .await を直接 使用できます。

async fn fetch_network_request() -> u32 {
    89
}

#[tokio::main]
async fn main() {
    let result = fetch_network_request().await;
    assert_eq!(result, 89);
}

macrosrt-multi-thread 機能を有効にして、tokioCargo.toml に追加してください。

[dependencies]
tokio = { version = "*", features = ["macros", "rt-multi-thread"] }

Builder アプローチ

tokio-badge std-badge

tokio::main はほとんどのプログラムでうまく機能しますが、設定に関するすべての判断をそれに任せることになります。 ランタイムをどのようにセットアップするかを自分で制御したい場合は、代わりに Builder を使用してください。

Builder はレシピのようなものだと考えてください。呼び出す各メソッドが、「使用するスレッド数」「それらの名前」「各スレッドに割り当てるメモリ量」といった指示を追加します。最後に .build() を呼び出すまで、実際には何も起こりません。.build() を呼び出した時点でランタイムが作成され、実行できる状態になります。

この例では、そのレシピは 4 つのワーカースレッドを設定し、それらに “thread-one” という名前を付け、各スレッドのスタックサイズを 3MB に設定しています。

use std::io;
use tokio::runtime::Builder;

async fn fetch_network_request() -> u32 {
    89
}

fn main() -> io::Result<()> {
     let runtime = Builder::new_multi_thread()
        .worker_threads(4)
        .thread_name("thread-one")
        .thread_stack_size(3 * 1024 * 1024)
        .build()?;

    runtime.spawn(async {
        let result = fetch_network_request().await;
        assert_eq!(result, 89);
    });

    Ok(())
}

rt-multi-thread 機能を有効にして、tokioCargo.toml に追加してください。

[dependencies]
tokio = { version = "*", features = ["rt-multi-thread"] }