From: Hiroshi IGARASHI Date: 2002-12-04T00:28:29+09:00 Subject: [ruby-list:36659] Re: Gtk.main いがらしです。 Ruby/GTK内部の話なのでruby-gnome-devel-jaに振ります。 At Tue, 3 Dec 2002 23:11:06 +0900, Masao Mutoh wrote: > > むとうです。 > > > なかだです。 > > シグナルでもmain_quitでもキューに貯めておくだけみたいで、問題な > > さそうです。その後でGtk.mainを呼んでいるスレッドを起こす必要が > > ありますが。 > > むとうさんの[ruby-list:36652]のサンプルに、puts "finished"の後 > > でGtk.main_quitとThread.main.runを追加すると処理が終ったところ > > で終了するようになりました。 > > あぁ、Thread.main.runに思い至りませんでした。 > > でも、ここで、runするThreadを明示的に指定しないといけないのって > なぜなのでしょうか。mainスレッドってずっと実行状態なのかなと > 思ってたのですが、そういうものではないのでしょうか。 > #また、激しく勘違いしてそうなのですが.....。 実際にtraceしてないので間違ってるかもしれませんが、 だいたいこんな感じのcall stackになってるはずです (RubyとCごちゃまぜ)。 mainスレッド Gtk.main gtk_main() ... rbgtk_poll() rb_thread_select() /* 重い処理スレッドに制御を渡す */ 重い処理スレッド Gtk.main_quit gtk_main_quit() gtk_main_quit()を呼んでも、mainスレッドはrb_thread_select() 内部で止まったままです。Thread.main.runでmainスレッドを 起こしてやると、rb_thread_select()からgtk_main()まで帰ってきて main loop終了検出、さらにGtk.mainも終了という流れになります。 よくある使い方だと思うので、Gtk.main, Gtk.main_quitに 面倒を見させるようにしてみました(CVS HEADからの差分)。 深く考えていないので、何か問題があるかも知れません。 # たぶんあります。 -- 五十嵐 宏 (Hiroshi IGARASHI) Index: src/rbgtkmain.c =================================================================== RCS file: /cvsroot/ruby-gnome/ruby-gnome/gtk/src/rbgtkmain.c,v retrieving revision 1.5 diff -u -p -r1.5 rbgtkmain.c --- src/rbgtkmain.c 4 Feb 2002 00:20:48 -0000 1.5 +++ src/rbgtkmain.c 3 Dec 2002 15:08:35 -0000 @@ -13,6 +13,8 @@ #include "global.h" +static VALUE rbgtk_main_threads = Qnil; + static VALUE gtk_m_events_pending(self) VALUE self; @@ -24,6 +26,7 @@ static VALUE gtk_m_main(self) VALUE self; { + rb_ary_push(rbgtk_main_threads, rb_thread_current()); gtk_main(); return Qnil; } @@ -40,6 +43,7 @@ gtk_m_main_quit(self) VALUE self; { gtk_main_quit(); + rb_thread_run(rb_ary_pop(rbgtk_main_threads)); return Qnil; } @@ -201,6 +205,8 @@ rbgtk_m_log_remove_handler(self, log_dom void Init_gtk_main() { rb_define_module_function(mGtk, "events_pending", gtk_m_events_pending, 0); + rb_global_variable(&rbgtk_main_threads); + rbgtk_main_threads = rb_ary_new(); rb_define_module_function(mGtk, "main", gtk_m_main, 0); rb_define_module_function(mGtk, "main_level", gtk_m_main_level, 0); rb_define_module_function(mGtk, "main_quit", gtk_m_main_quit, 0);