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