ATL Internals 2ed复习.chapter 3.CComGITPtr

来源:互联网 发布:数据库int设置取值范围 编辑:程序博客网 时间:2024/06/06 04:24

Global Interface Table (GIT)提供了进程内interface共享机制,用户可以高效的在套间之间传递interface.

使用GIT通常需要下面几步:

1..源套间在GIT中注册interface,需要调用IGlobalInterfaceTable系统服务,取得一个cookie

HRESULT RegisterMyInterface(IMyInterface* pmi, DWORD* pdwCookie) {  // this is usually a global  IGlobalInterfaceTable* g_pGIT = NULL;  HRESULT hr = ::CoCreateInstance(CLSID_StdGlobalInterfaceTable,                                  NULL,                                  CLSCTX_INPROC_SERVER,                                  IID_IGlobalInterfaceTable,                                  (void**)&g_pGIT);ATLASSERT(SUCCEEDED(hr));hr = g_pGIT->RegisterInterfaceInGlobal(pmi,  __uuidof(pmi), pdwCookie);return hr;}


2..目标套间由这个cookie取得在该套间有效的interface

HRESULT ReadMyInterface(DWORD dwCookie) {    // ... GIT pointer obtained elsewhere    IMyInterface* pmi = NULL;    hr = g_pGIT->GetInterfaceFromGlobal(dwCookie,    __uuidof(pmi), (void**)&pmi);    // use pmi as usual    return hr;}


3..用完之后,使用IGlobalInterfaceTable::RevokeInterfaceFromGlobal销毁这个cookie

 

CComGITPtr

template <class T> class CComGITPtr   {                      // ...               DWORD m_dwCookie;};                   


m_dwCookie是唯一的state

构造函数:

CComGITPtr() ;                       CComGITPtr(T* p);                    CComGITPtr(const CComGITPtr& git);   explicit CComGITPtr(DWORD dwCookie) ;


第一个m_dwCookie设置为0

第二个调用RegisterInterfaceInGlobal

第三个将会reregister,并将得到的cookie储存起来

最后一个在debug版本中将会验证cookie的正确性

CComGITPtr<T>& operator=(T* p)                    CComGITPtr<T>& operator=(const CComGITPtr<T>& git)CComGITPtr<T>& operator=(DWORD dwCookie)          


做的事情一样

析构函数:

~CComGITPtr() { Revoke(); }
HRESULT Revoke() {                                            HRESULT hr = S_OK;                                        if (m_dwCookie != 0) {                                        CComPtr<IGlobalInterfaceTable> spGIT;                     HRESULT hr = E_FAIL;                                      hr = AtlGetGITPtr(&spGIT);                                                                                          ATLASSERT(spGIT != NULL);                                 ATLASSERT(SUCCEEDED(hr));                                 if (FAILED(hr))                                               return hr;                                                                                                       hr = spGIT->RevokeInterfaceFromGlobal(m_dwCookie);        if (SUCCEEDED(hr))                                        m_dwCookie = 0;                                       }                                                         return hr;                                            }                                                         


 

HRESULT Attach(T* p) ;          HRESULT Attach(DWORD dwCookie) ;


第一个函数将会首先释放旧的cookie,然后对新的指针进行注册

第二个也会首先释放旧的,然后将新的cookie赋值到数据

 

DWORD Detach() ;

返回内部cookie,将内部cookie置0

 

 

对于目标套间,用户可以使用

HRESULT CopyTo(T** pp) const


例子:

HRESULT ReadMyInterface(const CComGITPtr<IMyInterface>& git) {    IMyInterface* pmi = NULL;    HRESULT hr = git.CopyTo(&pmi);    ATLASSERT(SUCCEEDED(hr));    //... use pmi as usual}

 

还应该防止多线程环境下的race condition,git会提前释放,此时应该使用WaitForSingleObject等手段:

void ThreadProc(void*);    // forward declarationHRESULT RegisterInterfaceAndFork(IMyInterface* pmi) {    CComGITPtr<IMyInterface> git(pmi); // interface registered    // create worker thread and pass CComGITPtr instance    ::_beginthread(ThreadProc, 0, &git);}void ThreadProc(void* pv){    CComGITPtr<IMyInterface>* pgit =        (CComGITPtr<IMyInterface>*)pv;    IMyInterface* pmi = NULL;    HRESULT hr = pgit->CopyTo(&pmi);    // ... do some work with pmi}


通常情况下,CComGITPtr不应该作为local变量