From: Masao M. <mu...@hi...> - 2006-03-07 14:41:39
|
むとうです。 On Tue, 07 Mar 2006 21:10:10 +0900 (JST) Kouhei Sutou <ko...@co...> wrote: > 須藤です. > > 現在,GLib::Object#signal_connectで登録したハンドラは自分で > 削除しないと削除されないようです. > > このため, > > object.signal_connect("XXX") do > ... > end > > というようにハンドラを登録すると,ハンドラがobjectの参照を持っ > たまま生き残ってしまい,objectがGCされません. <snip> > -- > 現状: > > 登録されたハンドラはCレベルのグローバルなハッシュテーブルに > 保存され,rubyのGCからも保護されています.このハッシュテーブ > ルにはハンドラとsignal_connectの第二引数以降の値を保存してい > ます. > > ハッシュテーブルの情報はグローバルなハッシュテーブルで管理さ > れているため,ハンドラが登録されているオブジェクトが死んでも > 生き残ります.このため,signal_handler_disconnectで明示的に > ハンドラを削除しないと,ハンドラが登録対象のオブジェクトを参 > 照しつづけるため,登録対象のオブジェクトがGCされません. > > 解決策案: > > ハッシュテーブルにハンドラだけではなく,登録対象のオブジェク > トを見付けることができる情報(idとかGObjectのポインタとか) > も含めておく.g_object_weak_refで登録対象のオブジェクトが死 > んだのを判断できるようにして,登録対象のオブジェクトが死んだ > らハッシュテーブルからハンドラを削除する. > > ただし,同じハンドラが複数のオブジェクトに登録されることもあ > るため,登録された回数とオブジェクトが死んだときにハンドラを > 削除する回数のバランスを保たないと,SEGVする気がする. > > こんな感じでよさそうな気がするけど,どうかなぁ. > > table = { > handler1 => [target_obj1, target_obj2], > handler2 => [target_obj1, target_obj3], > ..., > } > > ハンドラ登録: > > table[handler] ||= [] > table[handler] << target_obj > > ハンドラ削除: > table[table.index(handler), 1] = nil > table.delete(handler) if table[handler].empty? 行けそうな気がします。ぜひ試してみてくださいな。 1点、かなり以前にさかいさんが指摘されている 循環参照問題が絡んでくるかもしれませんのでその辺も注意してください。 http://www.tom.sfc.keio.ac.jp/~sakai/d/?date=20020802#c02 http://www.tom.sfc.keio.ac.jp/~sakai/d/?date=20020915 -- .:% Masao Mutoh<mu...@hi...> |