langsmith:164
From: Shiro Kawai <shiro lava.net>
Date: Thu, 30 Dec 2004 08:36:27 +0900
Subject: [langsmith:164] Re: continuationの実装について
継続の実装はいくつかバリエーションがありますが、本質的に
やることは「制御スタック(継続フレーム)の永続化」と言えると
思います。
Cで評価機を再帰呼び出ししている場合は、制御スタックがCの
スタックと混在してしまうために、(Cコンパイラを制御できない
限り)取れる戦略はほぼSCM方式(Cスタック全退避/復帰)に限ら
れると思います。この方法も万能ではなく、GCの配下に置かれない
リソース管理で面倒なことが起きるので、サードパーティの
Cライブラリから評価機がコールバックされる場合などは継続の
再開が出来ない可能性が高いです。
独自のインストラクションセットを持つ仮想マシンを導入しないでも、
Cスタックを回避する方法はいくつかあります。
ひとつは、全てのCルーチンをトランポリンで書くことです。
実装されている言語 (この場合Cipher) の制御スタックは自分で管理
します。一度評価機に制御を渡した後で戻り値を使って何かしたい
場合は、後半を明示的に別のCルーチンにして自前の制御スタックに
積みます(要するにCPSになる)。
この変形として、評価機再帰呼び出しとトランポリンの両方のAPIを
用意しておいて、継続は評価機再帰呼び出しがされた時点からの
部分継続である、としてしまう妥協もあります (Gaucheはこの方向)。
もうひとつも似たようなものですが、Cレベルで全てCPSで書いて
しまうというものです。Cルーチンは一切returnしないで、スタックが
溢れそうになったらスタックをスキャンして生きているフレームを
ヒープに移し、先頭にlongjmpします。実装されている言語のフレームは
Cのスタックフレーム中に作ります。
void foo(obj_t arg, frame_t *prev)
{
frame_t frame = { prev, ...}; /* 制御フレーム */
/* do something */
next(arg, &frame); /* won't return */
}
いずれもC側の呼び出しは複雑化しますが、その複雑化の要素は
定型的なものなので、自動生成することはできます。すなわち、
上記のようなCルーチンを生成するCへのトランスレータを書いて
しまう、というのがエレガントな解ではあると思います。
(もちろん、いろんな事情から、それが最適解にならない場合も
多々ありますが)。
--shiro
--
ML: langsmith quickml.atdot.net
使い方: http://www.atdot.net/~ko1/quickml
161 2004-12-29 23:25 [mogami brain.riken.g] continuationの実装について 162 2004-12-29 23:59 ┣[mogami brain.riken.g] 163 2004-12-30 00:18 ┃┗[matz ruby-lang.org ] -> 164 2004-12-30 08:36 ┗[shiro lava.net ] 165 2005-01-06 18:55 ┗[mogami brain.riken.g] 166 2005-01-08 07:45 ┗[shiro lava.net ]