ATL Internals 2ed复习.chapter 3.CComGITPtr

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 declaration
HRESULT 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变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值