初心者によるRustの非同期プログラミング

[OPTiM TECH BLOG Meetup 開催！#１「Rustの非同期プログラミングは何を実現するのか」](https://tech-blog.optim.co.jp/entry/2019/09/06/174000)へ参加したのがきっかけで、[Rust.Tokyo 2019](https://rust.tokyo)にもチケットを予約して、Rustの勉強を始めたiOSエンジニアです。

2019年11月リリース予定のRust1.39で遂にawait/asyncが正式対応する話でしたが、いち早く、試したくて、チャレンジした内容を紹介します。

# 動作確認環境
- MacBook Air
- macOS 10.14.4

# Rustをインストール
`curl -sSf https://sh.rustup.rs | sh`
Rustをインストール済みの場合は読み飛ばしてください。

# カレントのRustバージョンを確認する
```
rustc -V
```
2019年10月25日時点でrustc 1.38.0 (625451e37 2019-09-23)でした。

# Rust 1.39 betaへの切り替え方法
```
rustup install beta
rustup default beta
rustc -V
```
2019年10月25日時点でrustc 1.39.0-beta.6 (224f0bc90 2019-10-15)でした。

# デフォルトのツールチェインを切り替えずに、ディレクトリ単位で切り替える方法
詳しくはこちらを参照してください。
- [プロジェクトで使用するRustツールチェインのバージョンをチームで共有する](https://qiita.com/tatsuya6502/items/8b31e2b162aff78787fe)

# Rustによる非同期プログラミング(await)を試す
# Cargo.toml に runtime を追加します。
```
[dependencies]
runtime = "0.3.0-alpha.7"
```

# ソースコード
```
#![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; 
  } 
}
```
Rustによる非同期プログラミングで紹介されているソースコードを試しました。
https://ttis.croud.jp/?uuid=eafa5e19-1826-4700-9149-e2ad25f06a4e

# 実行結果
```
foo2:0 Thread[ThreadId(5)]
foo1:0 Thread[ThreadId(6)]
foo2:1 Thread[ThreadId(7)]
foo1:1 Thread[ThreadId(8)]
foo2:2 Thread[ThreadId(9)]
foo1:2 Thread[ThreadId(4)]
foo1:3 Thread[ThreadId(3)]
foo2:3 Thread[ThreadId(2)]
foo2:4 Thread[ThreadId(6)]
foo1:4 Thread[ThreadId(5)]
foo2:5 Thread[ThreadId(8)]
foo1:5 Thread[ThreadId(7)]
foo1:6 Thread[ThreadId(9)]
foo2:6 Thread[ThreadId(4)]
foo1:7 Thread[ThreadId(3)]
foo2:7 Thread[ThreadId(2)]
foo1:8 Thread[ThreadId(5)]
foo2:8 Thread[ThreadId(6)]
foo1:9 Thread[ThreadId(7)]
foo2:9 Thread[ThreadId(8)]
```

# 因みにRust 1.38でビルドするとawaitに対応していないので当然エラーになります。
```
error[E0658]: async blocks are unstable
  --> /Users/sam/.cargo/registry/src/github.com-1ecc6299db9ec823/runtime-raw-0.3.0-alpha.5/src/lib.rs:65:15
   |
65 |       let fut = async move {
   |  _______________^
66 | |         let t = fut.await;
67 | |         let _ = tx.send(t);
68 | |     };
   | |_____^
   |
   = note: for more information, see https://github.com/rust-lang/rust/issues/50547

error[E0658]: async/await is unstable
  --> /Users/sam/.cargo/registry/src/github.com-1ecc6299db9ec823/runtime-raw-0.3.0-alpha.5/src/lib.rs:66:17
   |
66 |         let t = fut.await;
   |                 ^^^^^^^^^
   |
   = note: for more information, see https://github.com/rust-lang/rust/issues/50547

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0658`.
error: Could not compile `runtime-raw`.
warning: build failed, waiting for other jobs to finish...
error: build failed
```

# 安定版Rustに戻す方法
```
rustup default stable
```