永井@知能.九工大です.

Tk の件で苦戦中に気付いたのですが,
safe-level って,proc 中でも閉じてるように見えるのですが,
これは正しいでしょうか?
もしそうなら,safe_block なんてメソッドがあると嬉しいかもしれません.
こんな感じです.
------------------------------
def safe_block(safe)
  proc{$SAFE=safe;yield}.call
end

p $SAFE     #=> 0
s = 'aaa'
p safe_block(2){p $SAFE; s += 'bbb'; 'ret'}  #=> 2 & "ret"
p s         #=> "aaabbb"
p $SAFE     #=> 0
------------------------------

safe-level が proc の中で閉じているのが仕様であるなら,
例の Tk での問題のを解決することができます.

問題は,「Tk の callback 中で,ある特定の safe-level で
処理を行った後にその結果を使って処理を継続したい」という状況です.
safe-level の wrap には Thread を使わねばならないとすると,
これを行うには Thread.new{}.value としなければなりません.(ですよね?)
ところが Tk の callback の場合,ここで待ち状態になるのは
Tk のイベントループです.
そのため,その thread の中で Tk を呼ぶと,
それを処理すべきイベントループは停止中ですので deadlock に陥ります.
また,これを予備のイベントループの起動によって回避しようとすると,
その予備イベントループの safe-level での実行になりますから,
余計なイベントまで間違えて処理しないようにしなければなりません.
それに,起動された thread 中で Tk を呼び出さないのであれば,
イベントループが deadlock に陥ることはありませんから,
その場合は予備のイベントループの起動は無意味です.

上記のような proc の使い方が許されれば,
イベントループがそのまま処理を行うことができ,
この件についての deadlock 問題を回避できます.
で,そうであるなら callback 中で起動する thread を
join/value する必要はなくなるはずですから,
「Tk の callback 中で起動する thread への join/value は禁止」
としてしまっても実用上の問題はないだろうと考えます.
詳細にはもう少し検討しないといけないですが,
これが OK なら問題は解決と言えそうに思います.
-- 
                                         永井 秀利 (九工大 知能情報)
                                             nagai / ai.kyutech.ac.jp