单例

49 阅读1分钟
#include <mutex>
template<typename T>
class c_singleton {
protected:
	c_singleton() = default;
	virtual ~c_singleton() = default;
	c_singleton(const c_singleton <T>&) = delete;
	c_singleton<T>& operator = (const c_singleton<T>&) = delete;

private:
	class c_garbo {
	public:
		c_garbo() = default;
		~c_garbo()
		{
			if (c_singleton<T>::m_pinstance) {
				delete c_singleton<T>::m_pinstance;
				c_singleton<T>::m_pinstance = nullptr;
			}
		}
		c_garbo(const c_garbo&) = delete;
		c_garbo& operator= (const c_garbo&) = delete;
	};

	static T* m_pinstance;
	static c_garbo garbo;
	static std::once_flag oc;

private:
	template<typename... Args>
	static void init(Args&&... args)
	{
		m_pinstance = new T(std::forward<Args>(args)...);
	}

public:
	template<typename... Args>
	static T* GetInstance(Args&&... args)
	{
		// 保证只调用一次
		std::call_once(oc, c_singleton<T>::init<Args...>, std::forward<Args>(args)...);
		return m_pinstance;
	}

	template<typename... Args>
	static bool IsInit()
	{
		return m_pinstance != nullptr;
	}
};
template<typename T>
T* c_singleton<T>::m_pinstance = nullptr;

template<typename T>
typename c_singleton<T>::c_garbo c_singleton<T>::garbo;

template<typename T>
std::once_flag c_singleton<T>::oc;


class c_test_singleton :public c_singleton<c_test_singleton>
{
public:
	void print(const char* str) {
		std::cout << "hello "<< str <<endl;
	}
};

int main()
{
	c_test_singleton::GetInstance()->print("world");
	getchar();
	return 0;
}
class c_singleton2
{
private:
	c_singleton2() = default;
	~c_singleton2() {
		if (m_pinstance != nullptr)
		{
			delete m_pinstance;
			m_pinstance = nullptr;
		}
	}

public:
	static c_singleton2* GetInstance()
	{
		std::call_once(oc, init);
		return m_pinstance;
	}

private:
	static void init()
	{
		m_pinstance = new c_singleton2();
	}

private:
	static c_singleton2* m_pinstance;
	static std::once_flag oc;
};
c_singleton2* c_singleton2::m_pinstance = nullptr;
std::once_flag c_singleton2::oc;

std::mutex g_mutex;
void print_instance_addr()
{
	c_singleton2* pinstance = c_singleton2::GetInstance();
	std::lock_guard<std::mutex> lock(g_mutex);
	std::cout << pinstance << endl;
}

int main()
{
	std::thread td[5];

	//multhread get instance addr;
	for (int i = 0; i < 5; i++)
	{
		td[i] = std::thread(print_instance_addr);
	}

	for (int i = 0; i < 5; i++)
	{
		td[i].join();
	}

	getchar();
	return 0;
}