stackfulness of coroutines
こんにちは、びしょ〜じょです。 気づいたら1月も終わりますね。 お前も俺も、もう終わりだ。
1. はじめに
研究ではコルーチンを使っている。 ここでひとつコルーチンについてまとめておきたい。 特にstackfulnessについての考察をこれまでおこなっていなかったため、そこに重点を置く。 本稿では文献[1]を参考にする。
2. 対称性による分類
コルーチンとは、一時停止、再開のできるサブルーチンを指す。 コルーチンを呼び出した呼び出し元にコントロールを戻す操作の有無により、コルーチンを対称コルーチンと非対称コルーチンの2種類に分けることができる(図2.1)。
対称コルーチン | 非対照コルーチン | |
---|---|---|
"戻る" 操作 | ない | ある |
対称コルーチンを持つプログラム言語は筆者は知らない。
非対称コルーチンはわりとメジャーな機能で、コルーチンやFiberと言われる言語機能は概ね非対称コルーチンと思われる。
"戻る" 操作とは、多くの非対称コルーチンを持つプログラム言語ではyield
というキーワードや関数名として使うことができる。
coroutine.create(function()
-- callerに"戻る"
coroutine.yield(3)
end)
3. stackfulnessによる分類
コールスタックをまたいで yieldできるかどうかで、非対称コルーチンをさらに2つに分類できる(表3.1)。
stackful | stackless | |
---|---|---|
またいでyield | できる | できない |
examples | Luaのcoroutine, RubyのFiber | Rustのcoroutine, JSのGenerator |
stackful coroutinesは単に "coroutine" 、 あるいは "fiber" と呼ばれ、 stackless coroutinesは "generator" と称される傾向にある。
では、 "コールスタックをまたげる" とはどういうことか? これはyieldがネストした関数呼出しから一気にコルーチンの呼び出し元まで戻れる、またyieldした位置にコントロールを戻せるということである。 次の例を見てみる(プログラム3.2, プログラム3.3)。
local send = function(x)
local y = yield(x)
return y + 3
end
local co = coroutine.create(function()
local x = send(10)
return x + 10
end)
print(resume(co)) -- prints 10
print(resume(co, 2)) -- prints 15
/* syntax error
function send(x) {
yield x
}
*/
const co = (function*() {
const x = yield 10
return x + 10
})
console.log(co.enxt()) // prints 10
console.log(co.next(3)) // prints 13
3.2を見てみる。
関数send
の中でyield
しているが、send
自体はただの関数である。
send
をコルーチンco
の中で呼び出すと、このyield
で一時停止する。
2度目のresume
で渡した2
が、yield
の戻り値となり、send
の戻り値は2 + 3
となる。
一方3.3は、コルーチン(generator)の中でしかyield
できない。
特にJSはyield
がキーワードとして扱われ、generatorの中でしか書けないというsyntacticな制約がある。
4. pros/cons
非対称コルーチンをさらにstaclful、stacklessの2種類に分類した。 利点と欠点をまとめてみると、次のようになる(表4.1)。
stackful | stackless | |
---|---|---|
利点 | 関数呼出しをまたいだyieldができ、 stacklessよりも表現力が高い |
ステートマシンに変換でき、実装が簡潔な だけでなく実行のパフォーマンスも良い |
欠点 | 実装が煩雑となり、コンテキストスイッチの オーバーヘッドがかかる |
表現力が低い |
stackful coroutinesの利点・欠点が、逆にstackless coroutinesの欠点・利点と、一長一短となっている。
5. 研究との関連性
筆者の研究では "ネストした関数呼出しから一気に飛び出せる" というstackful coroutinesの特性を利用している。 そのためstackless coroutinesではすぐには代替できない。 stackful coroutines → stackless coroutinesの変換がある場合はなんとかなるかもしれないので、教えてください。
6. おわりに
という話をゼミでやった。 (研究の進捗は)ないです
他
なんかわかりやすいやつ
-
Moura, Ana Lúcia De, and Roberto Ierusalimschy. "Revisiting coroutines." ACM Transactions on Programming Languages and Systems (TOPLAS) 31.2 (2009): 6. ↩