• 分享一个线程安全的单例模板类


    单例模式应该说是最简单的设计模式了。在此分享一个线程安全的单例模板类。

    template <typename Type>
    
    class CSingleton
    
    {
    
    public:
    
    static Type* GetInstance()
    
    {
    
    // kBeingCreatedMarker用来表示单例实例正在创建过程中。
    
    // 此处初始化为1是因为操作系统不会分配地址为1的指针。
    
    static const volatile intptr_t kBeingCreatedMarker = 1;
    
    // 如果m_pInstance不为空且不是正在创建,则返回m_pInstance
    
    if (m_pInstance != NULL && m_pInstance != kBeingCreatedMarker)  {
    
    return reinterpret_cast<Type*>(m_pInstance);
    
    }
    
    // 使用InterlockedCompareExchange函数保证原子操作
    
    // 函数判断m_pInstance是否等于NULL,如果是则将m_pInstance赋值为kBeingCreatedMarker
    
    // 函数返回值为m_pInstance的初始值,通过判断返回值是否等于NULL得知是否可以进行实例化
    
    if (InterlockedCompareExchange(
    
    reinterpret_cast<volatile LONG*>(&m_pInstance),
    
    static_cast<LONG>(kBeingCreatedMarker),
    
    static_cast<LONG>(NULL)) == NULL)  {
    
    static Type newval;
    
    m_pInstance = reinterpret_cast<intptr_t>(&newval);
    
    return &newval;
    
    }
    
    // 如果m_pInstance是kBeingCreatedMarker,即表示正在创建中
    
    // SwitchToThread让出剩余的时间片等待创建过程完成
    
    while (m_pInstance == kBeingCreatedMarker)
    
    {
    
    SwitchToThread();
    
    }
    
    // 到达此处表明创建过程已经完成了
    
    return reinterpret_cast<Type*>(m_pInstance);
    
    }
    
    Type& operator*()
    
    {
    
    return *GetInstance();
    
    }
    
    Type* operator->()
    
    {
    
    return GetInstance();
    
    }
    
    private:
    
    static volatile intptr_t m_pInstance;
    
    };
    
    template <typename Type>
    
    volatile intptr_t CSingleton<Type>::m_pInstance = NULL;

    假设我们有个CCmdManager类

    class CCmdManager
    
    {
    
    public:
    
    CCmdManager()
    
    {
    
    std::cout << "Hello, I am the only one!";
    
    };
    
    };

    使用方法很简单,如下:

    int main()
    
    {
    
    CCmdManager *pMgr = CSingleton<CCmdManager>::GetInstance();
    
    CCmdManager &mgr = *(CSingleton<CCmdManager>::GetInstance());
    
    }

    如果我们想要完全限制CCmdManager不被实例化第二次,我们可以这么做

    class CCmdManager
    
    {
    
    private:
    
    CCmdManager()
    
    {
    
    std::cout << "Hello, I am the only one!";
    
    };
    
    friend class CSingleton<CCmdManager>;
    
    };

    通过将构造函数设置为private,且仅对class CSingleton<CCmdManager>开放,就可以保证用户只能使用CCmdManager *pMgr = CSingleton<CCmdManager>::GetInstance()这种方式调用了。

    顺便说一下,这个代码的一些局限性

    1. 因为使用了InterlockedCompareExchange这个函数,所以只能在Windows下使用,但是不可否定的是这个函数的效率极高,完成比较并交换只要一条指令。

    wps2B92.tmp

    2. CSingleton在实例化对象时,只支持默认构造函数。一般情况下,这个也是可以接受的。

  • 相关阅读:
    hdu5894 hannnnah_j’s Biological Test(组合数取模)
    HDU5883 The Best Path(并查集+欧拉路)
    HDU5881 Tea(简单题)
    组合数取模
    codeforces703D Mishka and Interesting sum(区间偶数异或)
    upcoj2679 Binary Tree(思路题)
    upcoj2673 It Can Be Arranged(isap)
    atom编辑器适用
    python库pandas
    fabric Node SDK进行连接
  • 原文地址:https://www.cnblogs.com/SudoSky/p/4525648.html
Copyright © 2020-2023  润新知