• ATL 核心COM继承类之CComObjectRootEx及CComObjectLock


    参考:

    1. ATL 临界区

    2. ATL 引用计数线程模型

    • CComObjectRootEx Manages reference counting for both aggregated and nonaggregated objects. Allows you to specify a threading model.

    • CComObjectRoot Manages reference counting for both aggregated and nonaggregated objects. Uses the default threading model of the server.

    记住这句话就可以了:Manages reference counting.

    template <class ThreadModel>
    class CComObjectRootEx : 
        public CComObjectRootBase
    {
    public:
        typedef ThreadModel _ThreadModel;
        typedef typename _ThreadModel::AutoCriticalSection _CritSec;
        typedef typename _ThreadModel::AutoDeleteCriticalSection _AutoDelCritSec;
        typedef CComObjectLockT<_ThreadModel> ObjectLock;
    
        ~CComObjectRootEx() 
        {
        }
    
        ULONG InternalAddRef()
        {
            ATLASSUME(m_dwRef != -1L);
            return _ThreadModel::Increment(&m_dwRef);
        }
        ULONG InternalRelease()
        {
    #ifdef _DEBUG
            LONG nRef = _ThreadModel::Decrement(&m_dwRef);
            if (nRef < -(LONG_MAX / 2))
            {
                ATLASSERT(0 && _T("Release called on a pointer that has already been released"));
            }
            return nRef;
    #else
            return _ThreadModel::Decrement(&m_dwRef);
    #endif
        }
    
        HRESULT _AtlInitialConstruct()
        {
            return m_critsec.Init();
        }
        void Lock() 
        {
            m_critsec.Lock();
        }
        void Unlock() 
        {
            m_critsec.Unlock();
        }
    private:
        _AutoDelCritSec m_critsec;
    };
    
    template <>
    class CComObjectRootEx<CComSingleThreadModel> : 
        public CComObjectRootBase
    {
    public:
        typedef CComSingleThreadModel _ThreadModel;
        typedef _ThreadModel::AutoCriticalSection _CritSec;
        typedef _ThreadModel::AutoDeleteCriticalSection _AutoDelCritSec;
        typedef CComObjectLockT<_ThreadModel> ObjectLock;
    
        ~CComObjectRootEx() {}
    
        ULONG InternalAddRef()
        {
            ATLASSUME(m_dwRef != -1L);
            return _ThreadModel::Increment(&m_dwRef);
        }
        ULONG InternalRelease()
        {
    #ifdef _DEBUG
            long nRef = _ThreadModel::Decrement(&m_dwRef);
            if (nRef < -(LONG_MAX / 2))
            {
                ATLASSERT(0 && _T("Release called on a pointer that has already been released"));
            }
            return nRef;
    #else
            return _ThreadModel::Decrement(&m_dwRef);
    #endif    
        }
    
        HRESULT _AtlInitialConstruct()
        {
            return S_OK;
        }
    
        void Lock() 
        {
        }
        void Unlock() 
        {
        }
    };
    
    typedef CComObjectRootEx<CComObjectThreadModel> CComObjectRoot;
    

    CComObjectLockT

    为ComObject锁方法提供便利

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

    前后对比

    class CPenguin
        : public CComObjectRootEx<CComMultiThreadModel>, ... {
            STDMETHODIMP get_Wingspan(long* pnWingspan) {
                Lock();
                if( !pnWingspan ) return E_POINTER; // Forgot to Unlock
                *pnWingSpan = m_nWingspan;
                Unlock();
                return S_OK;
            }
            ...
    };
    
    class CPenguin
        : public CComObjectRootEx<CComMultiThreadModel>, ... {
            STDMETHODIMP get_Wingspan(long* pnWingspan) {
                ObjectLock lock(this);
                if( !pnWingspan ) return E_POINTER; // Unlock happens as
                // stack unwinds
                *pnWingSpan = m_nWingspan;
                return S_OK;
            }
            ...
    };
    
  • 相关阅读:
    Chrome浏览器的下拉选择框option有黑框的问题
    修改input checkbox和radio默认样式
    VsCode安装cssrem插件实现px转rem
    js实现小球的弹性碰撞
    CSS 技巧 -- 不定宽溢出文本适配滚动
    记忆化递归和递推
    DOM事件中target和currentTarget的区别
    TypeScripy + Vue Property Decorator + Vue Router,组件内的导航守卫无效
    行内元素没有内容时设置默认的宽高
    焦点元素,添加半透明遮罩
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2674899.html
Copyright © 2020-2023  润新知