COM組件的生命期控制

一、 提供生命期控制函數的必要性。 到目前爲止客戶對COM組件知道的僅僅是接口,因此客戶也就不能直接控制組件的生命週期。爲了客戶能夠更好的控制組件的生命週期,COM組件提供了一種直接控制單個接口生命週期來間接控制組件生命週期的方法。 二、 生命期控制。 1、 客戶不直接控制組件生命期的原因。 在客戶的代碼中,可能會有若干個指向此組件接口的指針。 例如:客戶的一部分通過一個指針使用組件的IX接口,另一部分通過另一個指針使用組件的IY接口,當不在使用IX接口時,可能還在使用IY接口。在這種情況下,當使用完一個接口時另一個接口可能還在被使用,因此組件是不能被釋放的。這就很難決定何時釋放掉組件。 COM組件採用的方法是,由COM組件提供對每個接口的引用計數控制,即IUnknown接口的AddRef和Release函數。客戶通過調用AddRef告訴組件開始使用這個接口,調用Release告訴組件使用完此接口。然後由組件自己決定是否釋放組件。 2、 COM組件使用接口級引用計數與使用組件級引用計數。 在用戶來看,引用計數處於接口級而不是組件級的原因如下: <1>、方便調試 用戶對接口操作時,很容易忘記調用Release函數,這就導致組件不能被釋放掉。若採用組件級的應用計數,查找的範圍是組件的所有接口;若採用接口級別引用計數查找的範圍只需要限制在某個接口。從查找範圍上來看採用接口級引用技術能夠縮小需要調試的範圍。 <2>、資源按需獲取 在實現一個接口時可能需要大量的內存和資源。若採用組件級的引用計數,只有當組件的所有接口都不再使用時,才能釋放資源(包括早已不再使用的資源);若採用接口級的引用技術當接口不再使用時,此與次接口關聯的資源就可以被釋放。能夠對不需要資源的及時釋放,節省資源。 三、 引用計數規則。 1、 輸出參數規則(即返回前調用AddRef規則)。 任何在輸出參數中或者作爲返回值返回一個接口指針的函數必須對此接口調用AddRef。 例如:HRESULT QueryInterface(const IID&, void**)在該函數返回前須調用AddRef。 2、 輸入參數規則。 對傳入函數的指針,無需調用AddRef和Release,原因是函數的生命期嵌套在調用者的生命期內。 例如: void FinalConstruct(IX* pIX) { pIX->Fx(); } 3、 輸入-輸出參數規則。 對於用輸入輸出參數來傳遞進來的接口指針,必須在該指針給它賦另一個接口指針值之前調用其Release。這種情況類似與調用重載的賦值函數一樣,需要先將就的資源釋放掉,然後在給其賦予新的自願。 4、 局部變量規則。 對於局部複製的接口指針,由於它們是在函數的生命期內才存在,因此無需調用AddRef和Release。 例如: void FinalConstruct(IX* pIX) { IX* pIX2 = pIX; pIX2->Fx(); } 5、 全局變量規則。 對於保存在全局變量中的接口指針,在將其傳遞給另外一個函數之前,必須調用AddRef,目的是防止在傳入函數中調用Release從而終止該接口的生命期。 例如: void FinalConstruct(IX* pIX) { pIX->Release(); } void main() { IX* pIX = NULL; HRESULT hr = QueryInterface(IID_IX, (void**)&pIX); if ( SUCCEED(hr) ) { pIX->AddRef(); FinalConstruct (pIX); pIX->Release(); } } 6、 不能確定時的規則。 當不確定該如何做時,需要調用AddRef和Release。 總結:通過IUnknown接口QueryInterface、AddRef和Release函數的可以看出,IUnknown接口的這三個函數可以對接口進行完全控制。 QueryInterface函數用來查詢組件支持的接口。 AddRef和Release函數用來控制接口的生命期,AddRef函數告訴組件客戶要使用接口。Release告訴組件客戶使用完了接口,可以從內存中釋放該接口。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章