About me
Rust素人
Rustで非同期処理を書いていたり、非同期処理を扱うライブラリを見ていると必ずと言っていいほどtokio
を利用しているケースに遭遇します。
tokio
の利用では#[tokio::main]
という謎の属性に遭遇しこれは一体何なのでしょう?
Rustのマクロを知る
Rustには2種類のマクロが提供されており、#[xxxx]
という属性は__手続き的マクロ__と呼ばれるものです。
これは属性を与えた型から新しいコードを生成するものです。
// 何も処理をしない関数に適当な属性を指定すると…
#[give_hello]
fn empty() {}
※give_hello
というマクロは存在しないのですが、雰囲気でこういうマクロがあるんだなと捉えてください。
// 以下のようなコードに変換される
fn empty() {
println!("Hello world!!")
}
ということで、#[tokio::main]
を指定した関数は何らかの処理が加えられた別の実装に置き換えられているのです。
どんな風に置き換えられるのか?
tokioのドキュメントにしっかり記述されています。
以下のように書いたコードは…
// tokioのドキュメントから抜粋
// See: https://docs.rs/tokio/1.10.1/tokio/attr.main.html#using-the-multi-thread-runtime
#[tokio::main]
async fn main() {
println!("Hello world");
}
以下のように評価されます。
// tokioのドキュメントから抜粋
// See: https://docs.rs/tokio/1.10.1/tokio/attr.main.html#using-the-multi-thread-runtime
fn main() {
tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap()
.block_on(async {
println!("Hello world");
})
}
この実装から、#[tokio::main]
はasync
キーワードをつけた関数を同期関数に変換し、
tokioのランタイムの中で非同期処理として実行させることがわかりました。
参考
Rustのドキュメント
https://doc.rust-jp.rs/book-ja/ch19-06-macros.html
tokioのドキュメント
https://docs.rs/tokio/1.10.1/tokio/attr.main.html
ありがとうございました。