//(1)设计模式大概谈
// 使得程序灵活,但是代码阅读非常的晦涩。
//(2)单例设计模式
// 使用频率比较高。只能创建一个对象。
#include<iostream>

using namespace std;

class MyCAS
{
private:
	MyCAS() {};      //私有化构造函数

private:
	static MyCAS* m_instance;

	class Release
	{
	public:
		~Release()
		{
			if (MyCAS::m_instance != nullptr)
			{
				delete MyCAS::m_instance;
				MyCAS::m_instance = nullptr;
			}
		}
	};

	static  Release r;

public:
	static MyCAS* GetInstance()
	{
		if (m_instance == nullptr)
		{
			m_instance = new MyCAS();
		}

		return m_instance;
	}

	void print()
	{
		cout << this << endl;
		cout << "test..." << endl;
	}
};

MyCAS* MyCAS::m_instance = nullptr;

int main()
{
	MyCAS* p_a = MyCAS::GetInstance();

	MyCAS* p_b = MyCAS::GetInstance();

	p_a->print();
	p_b->print();

	return 0;
}
//(3)单例设计模式共享数问题分析、解决
// 建议在主线程中创建其他线程之前就把单例类给创建完成。
#include<iostream>
#include<thread>
#include<mutex>

using namespace std;

std::mutex my_mutex;

class MyCAS
{
private:
	MyCAS() {};      //私有化构造函数

private:
	static MyCAS* m_instance;

	class Release
	{
	public:
		~Release()
		{
			if (MyCAS::m_instance != nullptr)
			{
				delete MyCAS::m_instance;
				MyCAS::m_instance = nullptr;
			}
		}
	};

	static  Release r;

public:
	static MyCAS* GetInstance()
	{
		if (m_instance == nullptr)
		{
			std::unique_lock<mutex> my_unique_lock(my_mutex);      //自动加锁
			if (m_instance == nullptr)
			{
				m_instance = new MyCAS();
			}
		}

		return m_instance;
	}

	void print()
	{
		cout << this << endl;
		cout << "test..." << endl;
	}
};

MyCAS* MyCAS::m_instance = nullptr;


//线程入口函数
void my_thread()
{
	MyCAS* p_a = MyCAS::GetInstance();
	p_a->print();
}

int main()
{
	thread thread1(my_thread);
	thread thread2(my_thread);

	thread1.join();
	thread2.join();

	return 0;
}
//(4)std::call_once()    函数模板,C++11引入的函数   该函数的第二个参数是一个函数名a,保证函数a只能调用一次。
//是具备互斥量的能力的,效率上比互斥量更高效。
//需要与一个std::once_flag配合使用
#include<iostream>
#include<thread>
#include<mutex>

using namespace std;

std::mutex my_mutex;

std::once_flag g_flag;      //系统定义的标记

class MyCAS
{
private:
	MyCAS() {};      //私有化构造函数

private:
	static MyCAS* m_instance;

	static void CreateInstance()     //只调用一次
	{
		cout << "CreateInstance() running ..." << endl;
		m_instance = new MyCAS();
		cout << "CreateInstance() finished" << endl;
	}

	class Release
	{
	public:
		~Release()
		{
			if (MyCAS::m_instance != nullptr)
			{
				delete MyCAS::m_instance;
				MyCAS::m_instance = nullptr;
			}
		}
	};

	static Release r;

public:
	static MyCAS* GetInstance()
	{
		std::call_once(g_flag, CreateInstance);     //call_once是一个原子操作,根据g_flag保证第二个参数中的函数只能被调用一次
		
		cout << "GetInstance finished..." << endl;

		return m_instance;
	}

	void print()
	{
		cout << this << endl;
		cout << "test..." << endl;
	}
};

MyCAS* MyCAS::m_instance = nullptr;


//线程入口函数
void my_thread()
{
	MyCAS* p_a = MyCAS::GetInstance();
	p_a->print();
}

int main()
{
	thread thread1(my_thread);
	thread thread2(my_thread);

	thread1.join();
	thread2.join();

	return 0;
}