#ifndef __SINGTON_H__
#define __SINGTON_H__
#include <mutex>
#include <iostream>
#include <atomic> // 解决reorder方案2
using namespace std;
//---------------------------------------------------
template <typename T>
class Sington {
public:
Sington() = delete;
Sington(const Sington& s) = delete;
~Sington() = delete;
// 解决reorder方案1
static T* getInstance() {
if (m_pInstance == nullptr) {
lock_guard<mutex> lock(m_mutex);
if (m_pInstance == nullptr) {
T* ptmp = new T(); // 网上说:巧妙的解决了编译器reorder代码时,先将地址赋值给m_pInstance后执行构造的问题。但是不知道会不会被编译器优化成m_pInstance = new T()?
m_pInstance = ptmp;
}
}
return m_pInstance;
}
// 解决reorder方案2
static T* getInstance2() {
T* tmp = m_pInstance2.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if (tmp == nullptr) {
lock_guard<mutex> lock(m_mutex);
tmp = m_pInstance2.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new T();
std::atomic_thread_fence(std::memory_order_release);
m_pInstance2.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
static void destroy() {
delete m_pInstance;
}
static void destroy2() {
}
private:
static T* m_pInstance; // 解决reorder方案1
static atomic<T*> m_pInstance2;
static mutex m_mutex;
};
template <typename T>
T* Sington<T>::m_pInstance = nullptr;
template <typename T>
atomic<T*> Sington<T>::m_pInstance2;
template <typename T>
mutex Sington<T>::m_mutex;
//---------------------------------------------------
class A {
public:
A(const A& a) = delete;
~A() {
cout << "A destroy" << endl;
}
void print() {
cout << m_data << " sington A print" << endl;
}
private:
A() {}
int m_data = 0;
friend class Sington<A>;
};
#endif // !__SINGTON_H__