ATL学习笔记(2): ATL对象多线程访问临界锁的实现

1. 几个临界区类

ATL将Windows临界区封装了一下,即CComCriticalSection和CComAutoCriticalSection类。两者的实现如下(精简):
class CComCriticalSection
{
public:
    CComCriticalSection()
    {  memset(&m_sec, 0, sizeof(CRITICAL_SECTION));   }
    HRESULT Lock()
    {  EnterCriticalSection(&m_sec); return S_OK; }
    HRESULT Unlock()
    { LeaveCriticalSection(&m_sec); return S_OK; }
    HRESULT Init()
    { 
 InitializeCriticalSection(&m_sec);
 return S_OK;
    }
    HRESULT Term()
    { DeleteCriticalSection(&m_sec); return S_OK; } 

    CRITICAL_SECTION m_sec;
};

class CComAutoCriticalSection : public CComCriticalSection
{
public:
    CComAutoCriticalSection()
    { HRESULT hr = CComCriticalSection::Init(); }
    ~CComAutoCriticalSection() 
    { CComCriticalSection::Term(); }
private:
    HRESULT Init();
    HRESULT Term();
};

CComCriticalSection类封装了一个临界区,以及对该临界区的初始化、锁定、解锁和释放操作。CComAutoCriticalSection是CComCriticalSection的一个子类,它实现了对临界区的自动初始化和释放。 CComAutoCriticalSection在构造和析构方法中嵌套了对临界去的初始化和释放操作,同时继承了锁定和解锁方法,并且把初始化和释放函数作了隐藏。

2. CComObjectRootEx类中的有关细节

CComObjectRootEx实现了线程安全的引用计数器,同时也声明了用于多线程同步访问对象的临界区和相关操作。CComObjectRootEx相关实现代码如下:

template < class ThreadModel >
class CComObjectRootEx : public CComObjectRootBase
{
public:
    typedef ThreadModel _ThreadModel;
    typedef _ThreadModel::AutoCriticalSection _CritSec;
    typedef CComObjectLockT<_ThreadModel> ObjectLock;

    ...    // 其他方法

    void Lock()   { m_critsec.Lock(); }
    void Unlock() { m_critsec.Unlock(); }
private:
    _CritSec m_critsec;
};

CComObjectRootEx提供了Lock和Unlock函数用来操作对象中的临界区,从而在多线程套间中,线程在访问互斥资源前,需要调用Lock来锁定临界区,在访问完毕后调用Unlock释放临界区,实现对象访问的线程安全性。当然,m_critsec在单线程套间中,将是一个伪临界区对象。

CComObjectRootEx中的Lock和Unlock函数必须成对使用。因而在一个分支较多的代码段中,必须确保每个分支在调用了Lock后都会调用Unlock。可是,疏忽有时候是难错免的,因此需要使用更安全的方法来实现Lock与Unlock的成对执行。这就是CComObjectLockT。

3. CComObjectLockT

首先看一下CComObjectLockT的实现。

template <class ThreadModel>
class CComObjectLockT
{
public:
    CComObjectLockT(CComObjectRootEx<ThreadModel>* p)
    {
        if (p) p->Lock();  
        m_p = p;
    }
    ~CComObjectLockT()
    {  if (m_p) m_p->Unlock(); }

    CComObjectRootEx<ThreadModel>* m_p;
};

CComObjectLockT在构造函数和析构函数中分别调用了CComObjectRootEx的Lock和Unlock。因此,如果将CComObjectLockT对象实例分配在栈里的话,在栈被撤销的时候,CComObjectLockT将被自动析构,Unlock也就自动被调用。一个例子:

HRESULT ComObject::put_Name (BSTR bstrName) 
{
    ObjectLock objlock(this);
    ......
}

在上述例子中,Unlock将在put_Name方法执行完毕后,随着objlock对象的析构而自动执行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值