LoginSignup
25
17

More than 3 years have passed since last update.

ついに正式対応されるRustのawait/asyncを1.39betaで確認してみた

Posted at

ついに正式対応されるRustのawait/asyncを1.39betaで確認してみた

こちらにも同じ内容を書いています

 2019年11月リリース予定のRust1.39でついにawait/asyncが正式対応となります。ここにたどり着くまでに色々な紆余曲折があったようです。

1.待機にawaitを使わない場合

ソースコード

 内容としてはファンクションを二つ用意して、中で10回ループ、ループごとに500msスリープを入れるという流れです。これをspawnで実行し、全ての処理が終了するまで待ちます。

 このコードでは通常のスレッド用Sleepを使って待機を行っています。

Test02.rs
#![allow(non_snake_case)]
use std::{thread, time};
async fn foo1() {
  for i in 0..10 {
    std::thread::sleep(time::Duration::from_millis(500));
    println!("foo1:{} Thread[{:?}]", i, thread::current().id());
  }
}
async fn foo2() {
  for i in 0..10 {
    std::thread::sleep(time::Duration::from_millis(500));
    println!("foo2:{} Thread[{:?}]", i, thread::current().id());
  }
}

#[runtime::main]
async fn main() {
  let handles = &mut [runtime::spawn(foo1()), runtime::spawn(foo2())];
  for handle in handles {
    handle.await;
  }
}

実行結果

 ThreadIdに特徴が現れていますが、完全にマルチスレッドの動きです。スレッドは切り替わらずに、単純にSleepに入っているのが分かります。

foo2:0 Thread[ThreadId(2)]
foo1:0 Thread[ThreadId(3)]
foo1:1 Thread[ThreadId(3)]
foo2:1 Thread[ThreadId(2)]
foo2:2 Thread[ThreadId(2)]
foo1:2 Thread[ThreadId(3)]
foo1:3 Thread[ThreadId(3)]
foo2:3 Thread[ThreadId(2)]
foo1:4 Thread[ThreadId(3)]
foo2:4 Thread[ThreadId(2)]
foo2:5 Thread[ThreadId(2)]
foo1:5 Thread[ThreadId(3)]
foo1:6 Thread[ThreadId(3)]
foo2:6 Thread[ThreadId(2)]
foo1:7 Thread[ThreadId(3)]
foo2:7 Thread[ThreadId(2)]
foo1:8 Thread[ThreadId(3)]
foo2:8 Thread[ThreadId(2)]
foo2:9 Thread[ThreadId(2)]
foo1:9 Thread[ThreadId(3)]

2.awaitを使用した場合

ソースコード

 ここではawait対応のSleepを使っています。

Test01.rs
#![allow(non_snake_case)]
use runtime::time::Delay;
use std::{thread, time};
async fn foo1() {
  for i in 0..10 {
    Delay::new(time::Duration::from_millis(500)).await;
    println!("foo1:{} Thread[{:?}]", i, thread::current().id());
  }
}
async fn foo2() {
  for i in 0..10 {
    Delay::new(time::Duration::from_millis(500)).await;
    println!("foo2:{} Thread[{:?}]", i, thread::current().id());
  }
}

#[runtime::main]
async fn main() {
  let handles = &mut [runtime::spawn(foo1()), runtime::spawn(foo2())];
  for handle in handles {
    handle.await;
  }
}

実行結果

 実行結果を見ると、スリープのawait待機でスレッドが切り替わっているのが分かります。どうやらasync/awaitの非同期処理は、スレッドそのものをいったん止めることで実現しているようです。

foo2:0 Thread[ThreadId(4)]
foo1:0 Thread[ThreadId(5)]
foo2:1 Thread[ThreadId(7)]
foo1:1 Thread[ThreadId(9)]
foo1:2 Thread[ThreadId(3)]
foo2:2 Thread[ThreadId(15)]
foo2:3 Thread[ThreadId(16)]
foo1:3 Thread[ThreadId(2)]
foo1:4 Thread[ThreadId(8)]
foo2:4 Thread[ThreadId(12)]
foo1:5 Thread[ThreadId(13)]
foo2:5 Thread[ThreadId(14)]
foo1:6 Thread[ThreadId(10)]
foo2:6 Thread[ThreadId(11)]
foo2:7 Thread[ThreadId(6)]
foo1:7 Thread[ThreadId(17)]
foo2:8 Thread[ThreadId(4)]
foo1:8 Thread[ThreadId(5)]
foo2:9 Thread[ThreadId(7)]
foo1:9 Thread[ThreadId(9)]

3.まとめ

 Rustがawait/asyncに対応することによって、通信やDB系の処理を書くときの利便性が向上が期待できます。今後、await/asyncを前提に対応がすすめられた便利なパッケージが増えれば、Rustの普及に弾みが付くかもしれません。

25
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
17