WebAssembly Coroutines
コルーチンとは
コルーチン(英: co-routine)とはプログラミングの構造の一種。サブルーチンがエントリーからリターンまでを一つの処理単位とするのに対し、コルーチンはいったん処理を中断した後、続きから処理を再開できる。接頭辞 co は協調を意味するが、複数のコルーチンが中断・継続により協調動作を行うことによる。
JavaScript だと(非対称)コルーチンが Generator Functions で実装することができる。
WebAssembly Coroutines
WebAssembly は最初の仕様が MVP だったため、コルーチンの機能は Future Features となっている。
具体的な提案。これを使えば WebAssembly でも容易にコルーチンが実装できそう。
今のところはまだそんな便利な命令はないため、実装にはコンパイル時に工夫が必要。
どう実装するか
愚直にトランスパイルする
Global や Memory にコルーチン内の変数を退避させ、さらに状態を指す変数を使って goto (switch) を実装すればよい。
code: (js)
function* generate() {
const a = 0;
const b = yield a;
yield b;
for (let i = 0; i < 5; ++i) {
yield i;
}
}
AssemblyScript Like な疑似コード
code: (ts)
let context: i32 = 0;
let a, b, i;
for (;;) {
switch (context) {
case 0:
a = 0;
context = 1;
case 1:
b = next;
context = 2;
case 2:
// loop init
i = 0;
case 3:
// loop end
if (!(i < 5)) {
context = 5;
break;
}
context = 4;
case 4:
++i;
context = 3;
break;
case 5:
}
}
}
SharedArrayBuffer と Atomics API を使う
WebAssembly を Web Worker 内で起動し、一時停止したい部分で atomics.wait する。
absurd-sql がこの方法を使っている。
参考
facebook/regenerator
コルーチンの実装を考える - Twitter
How to make coroutines in Wasm? - Stack Overflow
A future for SQL on the web