tokio::runtime::Handle でスレッドを跨ぐ

tokio::runtime::Handle を最近まで知らなくて無駄なコードを書いてたのでメモ。

Handle とは意味的には Runtime への参照になっている。
https://docs.rs/tokio/1.7.1/tokio/runtime/struct.Handle.html

Handle のドキュメントにもあるように、これを使うと現在のスレッドの Runtime への参照を取り出して別スレッドで同じ Runtime を使い回すことができる。

#[tokio::main]
async fn main() {
    let handle = tokio::runtime::Handle::current();
    std::thread::spawn(move || handle.block_on(run_in_child_thread()))
        .join()
        .unwrap();
}

async fn run_in_child_thread() {
    todo!()
}

同様に tokio の非同期なコードと rayon のようなスレッドによるデータ並列なコードを組み合わせるのも Handle を使えば簡単にできる。

use rayon::prelude::*;

#[tokio::main]
async fn main() {
    let handle = tokio::runtime::Handle::current();

    [1, 2, 3].into_par_iter().for_each(|i| {
        handle.block_on(async {
            cpu_intensive_func1(i);
            tokio::time::sleep(tokio::time::Duration::from_secs(i)).await;
            cpu_intensive_func2(i);
            println!("Finished {}", i);
        });
    });
}