#Gaucheの継続の制限 (Cスタックをまたいだ継続では、待ち受けているC関数に2回以上戻れない) をどうやって説明しようかと悩んでいたんだけれど、これはスタック云々の話ではなくリソースの話だと考えれば良いのじゃないか、と気づいた。
#例えば継続捕捉時にopenされていたファイルが閉じられたら、その後で継続を起動して戻ってもファイルは閉じられたままである。これは当然。
#同様に、Cのスタックというのは有限のエクステントを持つ資源で、一度returnしたら解放されちゃうので、2度目以降にそこを通過しようとしたら使えない。
#そのリソースに触らなければ、継続を何度起動しようが問題ない.
#Cスタックの場合であれば、それに触るのは継続がそこまで巻戻った時だけだから、そこまで巻き戻る前に別の継続に脱出するなら、何度起動しても問題ない。
#同じ理屈で、一つのスレッドで捕まえた継続を別スレッドで起動する場合も説明できるかな。どこまでも巻戻れるわけじゃないということ。
#たとえば、GLUT のコールバックの中から継続を呼び出した場合とか、ですか?
#ああ、それよりも、GLUT の中で継続を補足して、それを別のタイミングで呼び出したりした場合か。
#0.9.1では、呼び出すのは問題ないです。ただ、理屈の上ではGLUTのコールバックで補足した継続はそこからGLUTのメインループに戻るべきと考えられますが、Cルーチンへのreturnは1回しか許されないため、継続がコールバックの残りを実行してreturnしたところでエラーになります。
#コールバックの残りを実行した後で別の継続を呼ぶことで、Cルーチンへのreturnを避けるなら問題ありません。部分継続はそういう目的でも使えます (コールバックに入ったところでresetかけておけば、部分継続を実行した場合はresetまで進んだところで継続を呼び出したところに戻ってくる)。
#…というような説明をうまくマニュアルに書くのが難しいなあと思って悩んでいたのです。
#あれ、書き込み失敗しちゃったかな。なるほど、それはまた別の問題なんですね。
#問題としてはluaのyieldの制限
#と同じ根っこだと思います。
#ああ、そうそう、最近それでちょっと躓いていたんです。
#lua だと pcall っていうエラー捕捉機能付きの関数呼び出しの中で coroutine.yield() をすると、そんなようなエラーメッセージが出て怒られます。でも、実はまだ完全には理解できてません。
#をフォローすると興味深い話が見られる。今はネイティブなコールスタックなどとSchemeの継続やLuaのコルーチンなどの間で起こるインピーダンスミスマッチの話
#あ、mentionしたら転送されるんですね、ごめんなさい。あと、C言語から呼び出したLuaコードのyieldは5.2で可能になる予定……だったはず
#インピーダンスミスマッチというんですか。インピーダンスってソレノイドコイルに電流を流したときの何かでしたっけ。
#いまでも、C から呼び出したコードから yield することはできてるはず。ゲームのロジックを書くのに、わりと日常的に使っているので。
#ああでも、コールスタックが C->Lua->C->Lua みたいになってるときに、yield したらどうなるんだろう。
#はい。電気工学のインピーダンスの不一致になぞらえて、考え方や設計の異なる二者(例:関係モデルとオブジェクト)を接続する(例:O/Rマッピング)際に起きる不協和音をインピーダンスミスマッチと呼ぶことがあります
#インピーダンスは「抵抗」を交流に拡張したもの(あるいは複素数に拡張したもの
#)。で、渡す側と受ける側のインピーダンスが合ってないとエネルギーの伝達効率が落ちる
#ってとこから来てるんでしょうねえ。
#そうですね、表現が不適切でした。C→Luaだと問題は起きませんが、Lua→C→Luaのような場合に問題が起きます。pcallとの関連は http://lua-users.org/wiki/PcallAndCoroutines #それはほぼどうしようもないでしょう。中に挟まってるCのスタックは一度returnしたら消えちゃうから。SCMの継続のようにCスタックをコピーして保存しておくという荒技はあるけれど、C言語書く人はひとつの関数から2回戻ってきても大丈夫なようには普通書かないし。さらにC++だとauto変数に対してデストラクタが呼ばれてるだろうからスタックコピーでまともに動かすのはmazu無理。
#s/mazu/まず/ Enterで投稿できるのはスピーディでいいんだけど時々早まっちゃうな。投稿後10秒以内なら修正できる、とかいう機能があるとうれしいだろうか。
#ああそうか。ゲームエンジンが C なので、常に C->Lua を前提に考えてしまってました。
#ああ、あれ、上で shiro さんが問題にしているのは、関数から値が 2 度返ってくるのとは別の問題なんですよね。
#Lua 5.2では http://lua-users.org/wiki/ResumableVmPatch に近いやり方でANSI Cから逸脱せずにyieldとの親和性を高めた、らしいです(無精にもfinalが出てからコードを読もうとしている) #同じ問題と言えるんじゃないかなあ。Cから見てScm_Eval()が2度帰ってくるって話になるので (実際には、2度目には帰る先が既に無いことが多いので、帰る前にエラーにしている)
#ああ、なら、ちょっと分かりました。
#Luaのyieldはcoroutine限定で、continuation (何回でも起動できる) ってわけじゃない…で合ってますか。上のResumableVmPatchのページを読んでたんだけど。
#それなら工夫の余地はあるかな、と思ったんで。
#pcall から yield できないのは、Lua が本物の継続を持ってないから、と思ってました。(上のページはまだ読んでないですけど)
#coroutineに限定すると、継続はmaxで1回しか起動できなくて良いので、実装上の選択肢は完全な継続よりも増えますね。Luaの実装がどうか詳しくは知らないですけど。
#あ、はい。coroutine の中からしか yield は呼べません。
#はい、自分の知る範囲ではLuaのyieldは継続ではなかったはずです。少し探したら、どう対処するのかが http://www.lua.org/work/doc/manual.html#4.7 にありました #そうそう、そのlua_callkみたいのが、GaucheのScm_VMPushCCに相当するんじゃないかな。Gaucheの場合、継続安全にCからSchemeを呼びたい時はScm_VMPushCCでCの継続手続きを積んでからScm_VMApply()をtail callする。
#あー、継続として呼ばれたらこの関数を呼んでね、っていって、関数ポインタを渡すんですね。
#先日のILCアンケートの件、みなさま回答ありがとうございました。おかげさまで貴重な意見が頂けました。
#ありがとうございます。
#どうもお久しぶりです。個人的にChatonを使わせてもらっています。
##当分はまだ改造を続ける予定です。とりあえず報告でした。
##ども。いくつか機能を頂くかもしれません。
#confファイルの値が全部文字列なのは何か理由があったと思うんだけど何でだったかな。
#build-siteで簡易sedしながら置き換えるのに文字列だと便利だからか。それだけならconfigを読む時点で最終値を文字列に変換しても良さそうだ。
#confファイルは「様々なファイル中の文字列置換を定義する」という位置づけなので、文字列→文字列でないと混乱すると思ったのかも。Schemeファイルだけが対象ならScheme値で良いんだけど、それ以外のファイルも対象だから、その時にSchemeの値がどういう文字列として解釈されるかがわかりにくい。