//懒汉模式:lazy load  只有用了才加载  复杂场景下也可以使用
namespace LAZY
{
    class Lock
    {
    public:
        Lock(mutex& mux) :_mux(mux){
            //_mux.lock();
        }
        ~Lock(){
            //_mux.unlock();
        }
        //防拷贝
    protected:
        Lock(const Lock& mx);
        Lock& operator=(const Lock& mx);
    private:
        mutex& _mux;
    };
    class Singleton
    {
    public:
        //判断是否为空,如果为空则创建,不为空就直接返回
        static Singleton* GetInstance()
        {
            //加锁线程安全,如果中间返回了会造成死锁  所以自己写了一个
            //mu.lock();
            lock_guard<mutex> lock(mu);
            // 双检查
            if (_ints == NULL)
            {
                Lock lock(mu);
                if (_ints == NULL)
                {           
                    Singleton* tmp = new Singleton;
                    //内存栅栏  栅栏之后和之前的语句不能被打乱 防止编译器对程序进行优化
                    MemoryBarrier();
                    _ints = tmp;
                }
            }
            //mu.unlock();
            return _ints;
        }
        //销毁单例模式
        static void DelInstance()
        {
            lock_guard<mutex> lock(mu);
            if (_ints)
            {
                cout << "test if delete" << endl;
                delete _ints;
                _ints = NULL;
            }
        }
        //防拷贝,只声明不实现
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);
        void Print()
        {
            cout << "Singleton:" << _a << endl;
        }
    private:
        //将构造函数声明为私有
        Singleton() :_a(0)
        {}
        int _a;
        static mutex mu;
        static Singleton* _ints;
    };
    Singleton* Singleton::_ints = NULL;
    mutex Singleton::mu;
    void test()
    {
        Singleton::GetInstance()->Print();
        //如果在此之后还有人创建单例怎么办??所以最好不要手动释放
        //Singleton::DelInstance();
        atexit(Singleton::DelInstance);
    }
}
//饿汉模式:程序运行就创建  简洁,适用性会受到限制  
namespace HUNGRY
{
    class Singleton
    {
    public:
        static Singleton& GetInstance()
        {
            static Singleton inst;//进来第一次创建  后面进来不再创建,直接返回
            return inst;
        }
        void Print()
        {
            cout << "Singleton:" << _a << endl;
        }
    protected:
        Singleton() :_a(0)
        {}
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);
        int _a;
    };
    void test1()
    {
        Singleton::GetInstance().Print();
    }
}
int main()
{
    //HUNGRY::test1();
    LAZY::test();
    system("pause");
    return 0;
}