I'm working with C++11 and I'm trying to implement a singleton which works at multi-threading project.
template <typename T>
class Singleton
{
public:
Singleton(const Singleton&&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator=(const Singleton&) = delete;
Singleton& operator=(Singleton&&) = delete;
static T* getInstance()
{
static Protector protector {instance};
return instance;
}
template<typename... Args>
static void createInstance(Args&&... args) {
static T t(std::forward<Args>(args)...);
instance = &t;
}
private:
Singleton() = default;
~Singleton() = default;
static T* instance;
struct Protector {
Protector(T* p) {
if (p == nullptr) {
assert("not-init");
}
}
};
};
template<typename T>
T* Singleton<T>::instance = nullptr;
class Test
{
friend class Singleton<Test>;
private:
Test(int aa): a{aa} {};
~Test(){};
int a;
public:
void print(void) {std::cout << "hello " << a << std::endl;}
};
int main(void)
{
Singleton<Test>::createInstance(1);
Singleton<Test>::getInstance()->print();
return 0;
}
I've known that the initialization of static
variable is thread safe in C++11 so I think this shouldn't cause any problem (https://stackoverflow.com/a/1661564/3305546).
The inner class named Protector
is used to make sure that createInstance()
has been called before calling getInstance()
. I think this should be OK too.
But after reading this link, it seems that instance = &t;
in the funciton createInstance()
could cause race condition if the function is called in multi threads? If so, what is the proper way to solve this issue? Replace static T* instance
with std::atomic<T*> instance
?
Aucun commentaire:
Enregistrer un commentaire