前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ATL源码学习---线程模型支持

ATL源码学习---线程模型支持

作者头像
雪影
发布2018-08-02 14:23:16
8660
发布2018-08-02 14:23:16
举报
文章被收录于专栏:流媒体人生流媒体人生

1.线程锁的类型

  线程锁类型有CComCriticalSection,CComAutoCriticalSection、 CComSafeDeleteCriticalSection、CComAutoDeleteCriticalSection、 CComFakeCriticalSection。每种锁都有它们的特定用途。

代码语言:javascript
复制
[c-sharp] view plain copy
代码语言:javascript
复制
// COM Sync Classes 
class CComCriticalSection  
{  
public:  
    CComCriticalSection() throw()  
    {  
        memset(&m_sec, 0, sizeof(CRITICAL_SECTION));  
    }  
    ~CComCriticalSection()  
    {  
    }  
    HRESULT Lock() throw()  
    {  
        EnterCriticalSection(&m_sec);  
 return S_OK;  
    }  
    HRESULT Unlock() throw()  
    {  
        LeaveCriticalSection(&m_sec);  
 return S_OK;  
    }  
    HRESULT Init() throw()  
    {  
        HRESULT hRes = E_FAIL;  
        __try  
        {  
            InitializeCriticalSection(&m_sec);  
            hRes = S_OK;  
        }  
 // structured exception may be raised in low memory situations 
        __except(STATUS_NO_MEMORY == GetExceptionCode())  
        {             
            hRes = E_OUTOFMEMORY;         
        }  
 return hRes;  
    }  
    HRESULT Term() throw()  
    {  
        DeleteCriticalSection(&m_sec);  
 return S_OK;  
    }     
    CRITICAL_SECTION m_sec;  
};  
class CComAutoCriticalSection : public CComCriticalSection  
{  
public:  
    CComAutoCriticalSection()  
    {  
        HRESULT hr = CComCriticalSection::Init();  
 if (FAILED(hr))  
            AtlThrow(hr);  
    }  
    ~CComAutoCriticalSection() throw()  
    {  
        CComCriticalSection::Term();  
    }  
private :  
    HRESULT Init(); // Not implemented. CComAutoCriticalSection::Init should never be called 
    HRESULT Term(); // Not implemented. CComAutoCriticalSection::Term should never be called 
};  
class CComSafeDeleteCriticalSection : public CComCriticalSection  
{  
public:  
    CComSafeDeleteCriticalSection(): m_bInitialized(false)   
    {  
    }  
    ~CComSafeDeleteCriticalSection() throw()  
    {  
 if (!m_bInitialized)  
        {  
 return;  
        }  
        m_bInitialized = false;  
        CComCriticalSection::Term();  
    }  
    HRESULT Init() throw()  
    {  
        ATLASSERT( !m_bInitialized );  
        HRESULT hr = CComCriticalSection::Init();  
 if (SUCCEEDED(hr))  
        {  
            m_bInitialized = true;  
        }  
 return hr;  
    }  
    HRESULT Term() throw()  
    {  
 if (!m_bInitialized)  
        {  
 return S_OK;  
        }  
        m_bInitialized = false;  
 return CComCriticalSection::Term();  
    }  
    HRESULT Lock()  
    {  
 // CComSafeDeleteCriticalSection::Init or CComAutoDeleteCriticalSection::Init 
 // not called or failed. 
 // m_critsec member of CComObjectRootEx is now of type  
 // CComAutoDeleteCriticalSection. It has to be initialized 
 // by calling CComObjectRootEx::_AtlInitialConstruct 
        ATLASSUME(m_bInitialized);  
 return CComCriticalSection::Lock();  
    }  
private:  
 bool m_bInitialized;  
};  
class CComAutoDeleteCriticalSection : public CComSafeDeleteCriticalSection  
{  
private:  
 // CComAutoDeleteCriticalSection::Term should never be called 
    HRESULT Term() throw();  
};  
class CComFakeCriticalSection  
{  
public:  
    HRESULT Lock() throw() { return S_OK; }  
    HRESULT Unlock() throw() { return S_OK; }  
    HRESULT Init() throw() { return S_OK; }  
    HRESULT Term() throw() { return S_OK; }  
};  

2.线程锁的封装,实现锁类型的参数化

代码语言:javascript
复制
[cpp] view plain copy
代码语言:javascript
复制
template< class TLock >  
class CComCritSecLock  
{  
public:  
    CComCritSecLock( TLock& cs, bool bInitialLock = true );  
    ~CComCritSecLock() throw();  
 HRESULT Lock() throw();  
 void Unlock() throw();  
// Implementation 
private:  
    TLock& m_cs;  
 bool m_bLocked;  
// Private to avoid accidental use 
    CComCritSecLock( const CComCritSecLock& ) throw();  
    CComCritSecLock& operator=( const CComCritSecLock& ) throw();  
};  
template< class TLock >  
inline CComCritSecLock< TLock >::CComCritSecLock( TLock& cs, bool bInitialLock ) :  
    m_cs( cs ),  
    m_bLocked( false )  
{  
 if( bInitialLock )  
    {  
 HRESULT hr;  
        hr = Lock();  
 if( FAILED( hr ) )  
        {  
            AtlThrow( hr );  
        }  
    }  
}  
template< class TLock >  
inline CComCritSecLock< TLock >::~CComCritSecLock() throw()  
{  
 if( m_bLocked )  
    {  
        Unlock();  
    }  
}  
template< class TLock >  
inline HRESULT CComCritSecLock< TLock >::Lock() throw()  
{  
 HRESULT hr;  
    ATLASSERT( !m_bLocked );  
    hr = m_cs.Lock();  
 if( FAILED( hr ) )  
    {  
 return( hr );  
    }  
    m_bLocked = true;  
 return( S_OK );  
}  
template< class TLock >  
inline void CComCritSecLock< TLock >::Unlock() throw()  
{  
    ATLASSUME( m_bLocked );  
    m_cs.Unlock();  
    m_bLocked = false;  
}  

3.ATL线程模型定义

代码语言:javascript
复制
[cpp] view plain copy
代码语言:javascript
复制
class CComMultiThreadModel  
{  
public:  
 static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);}  
 static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);}  
 typedef CComAutoCriticalSection AutoCriticalSection;  
 typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection;  
 typedef CComCriticalSection CriticalSection;  
 typedef CComMultiThreadModelNoCS ThreadModelNoCS;  
};  
class CComSingleThreadModel  
{  
public:  
 static ULONG WINAPI Increment(LPLONG p) throw() {return ++(*p);}  
 static ULONG WINAPI Decrement(LPLONG p) throw() {return --(*p);}  
 typedef CComFakeCriticalSection AutoCriticalSection;  
 typedef CComFakeCriticalSection AutoDeleteCriticalSection;  
 typedef CComFakeCriticalSection CriticalSection;  
 typedef CComSingleThreadModel ThreadModelNoCS;  
};  
class CComMultiThreadModelNoCS  
{  
public:  
 static ULONG WINAPI Increment(LPLONG p) throw() {return InterlockedIncrement(p);}  
 static ULONG WINAPI Decrement(LPLONG p) throw() {return InterlockedDecrement(p);}  
 typedef CComFakeCriticalSection AutoCriticalSection;  
 typedef CComFakeCriticalSection AutoDeleteCriticalSection;  
 typedef CComFakeCriticalSection CriticalSection;  
 typedef CComMultiThreadModelNoCS ThreadModelNoCS;  
};  

ATL中把不同线程模型下引用计数的实作封装到同一个函数中:加法是Increment(),减法是Decrement() 。三个代表不同线程模型的类:CComSingleThreadModel、CComMultiThreadModel CComMultiThreadModelNoCS 中均实作了这两个函数。这样,我们只需要把线程模型当作模板参数传递给对象,对象就能获得正确的引用计数操作动作。

其中有3种临界区 CComCriticalSectionCComAutoCriticalSectionCComFakeCriticalSection 。每一个临界区都提供了统一的4种操作来操作临界区:Lock() Unlock() Init() Term() 。我们在程序中使用“临界区”时,只需要调用这四种操作就可以达到保护数据成员不被其他线程修改的目的。

4.服务器的默认线程模型

代码语言:javascript
复制
[cpp] view plain copy
代码语言:javascript
复制
#if defined(_ATL_SINGLE_THREADED) 
#if defined(_ATL_APARTMENT_THREADED) || defined(_ATL_FREE_THREADED) 
#pragma message ("More than one global threading model defined.") 
#endif 
 typedef CComSingleThreadModel CComObjectThreadModel;  
 typedef CComSingleThreadModel CComGlobalsThreadModel;  
#elif defined(_ATL_APARTMENT_THREADED) 
#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_FREE_THREADED) 
#pragma message ("More than one global threading model defined.") 
#endif 
 typedef CComSingleThreadModel CComObjectThreadModel;  
 typedef CComMultiThreadModel CComGlobalsThreadModel;  
#elif defined(_ATL_FREE_THREADED) 
#if defined(_ATL_SINGLE_THREADED) || defined(_ATL_APARTMENT_THREADED) 
#pragma message ("More than one global threading model defined.") 
#endif 
 typedef CComMultiThreadModel CComObjectThreadModel;  
 typedef CComMultiThreadModel CComGlobalsThreadModel;  
#else 
#pragma message ("No global threading model defined") 
#endif 

ATL内部使用CComObjectThreadModel来保护组件内部实例数据,CComGlobalThreadModel来保护全局和静态数据。

ATL提供了 CComObjectRootEx模板类,来封装上面关于引用计数的操作以及临界区的操作。只要提供给CComObjectRootEx一个代表其线程模型的模板参数,它就能实作出InternalAddRef()、InternalRelease()以及Lock()和UnLock()四个统一的操作界面。

经过了这么多层封装,ATL 已经把AddRef()和Release()所需要的操作全部实作出来了,可是ATL还是没有迈出最后的一步——没有把这些操作整合进AddRef()和 Release(),这是因为ATL还要考虑聚合的因素。在聚合的情况下,COM对象的AddRef()和Release()操作都和独立激活时候完全不同。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2009年09月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档