#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];
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;
}