なんか自分で整理できていない気がするので、書きながら整理してみよう。
WIN32OLEオブジェクト1つとそのイベントに
反応するWIN32OLE_EVENTオブジェクトが1つあったとする。
GCされるときには、
先にWIN32OLEオブジェクトがGCされる。
先にWIN32OLE_EVENTオブジェクトがGCされる。
2.の場合には、WIN32OLE_EVENTオブジェクトがGCされると
それ以降、WIN32OLEオブジェクトのメソッドを呼び出しても
イベントを拾うことができない。
だから、WIN32OLEオブジェクトが存在し続ける限り、
WIN32OLE_EVENTも存在し続けた方が良い。
そこで、WIN32OLE_EVENTはGCされないように
win32ole内部のグローバルな配列に追加している。
だが、WIN32OLEオブジェクトが存在し続ける間だけ、
WIN32OLE_EVENTが存在し続ければ良いのだから、
WIN32OLEオブジェクトにWIN32OLE_EVENTオブジェクトの配列を
メンバーとして持たせれば良い。
...ような気がしてきた。
[ruby-dev]の問題は、このグローバルな配列の件とは別で、
次のような問題だったような気がしてきた。
WIN32OLE_EVENTオブジェクトがGCされるとき、
IConnectionPoint->Unadviseを実行して、OLEサーバーに
イベントを送ってこなくていいよと伝える。
OLEサーバーは参照カウントを1つ減らし、
OLEサーバーは、WIN32OLE_EVENT側のReleaseを呼び出す。
WIN32OLE_EVENT(がアロケートした領域)は、OLEサーバーからの
Releaseの呼び出されるまで存在し続けなければならない。
なので、GCのタイミングでWIN32OLE_EVENTの領域をfreeできないのである。
...というのが問題だったんじゃなかったかな。
つまり、WIN32OLE_EVENTのGCのタイミングでは領域をfreeしないで
Releaseが呼ばれたときに領域をfreeしてしまえば良い
...のかな。
いや、逆にWIN32OLE_EVENTオブジェクトがGCされる前にWIN32OLE_EVENT側の
Releaseが呼ばれる場合もあったような...。
ということで、試してみることは、
WIN32OLE_EVENTオブジェクトを保持するグローバル配列を廃止する。
WIN32OLEオブジェクトにWIN32OLE_EVENTオブジェクトを保持する配列のメ
ンバを追加する。
ole_event_free と EVENTSINK_Releaseのどちらが先に呼ばれるか
再確認する。(1.と2.の修正がうまくいった上で)
[ruby-dev]の問題の対策を考え直す。
とりあえず、1.と2.を片付けてから 3.と4.だな。
最近のコメント