I want to create a thread safe singleton class.
The current way to achieve the same(that I know of) is by having a static method in the class which returns the static object as below:
Singleton & Singleton::getInstance()
{
static Singleton instance;
return instance;
}
The problem with having this approach is that since the created object is static, its cleanup happens at application exit. Ideally I would like to have control over when the destruction exactly happens.
I did some digging and found that I can use the static ptr to instance way and have a separate cleanup function, but to make it thread safe I will have to use double check locking with explicit memory barriers.
Is there a simpler to comprehend(I am not an expert) way to achieve the same?
Related
I am writting a thread safe singleton class as follows. The following implementation ensures that only one instance of the class in created. My use case is that I am using this instance in a multi thread environment where each thread may call getInstance() and do some work using the instance. My question is how can I ensure that only one thread is using the instance at a particular time, so as to prevent race conditions that might occur if multiple threads are trying to use the single instance at same time.
class Singleton {
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton& getInstance() {
static Singleton s;
return s;
}
};
One thing you could do is to just make all it's members thread safe by locking a mutex.
class Singleton {
Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
std::mutex my_mutex_member;
public:
static Singleton& getInstance() {
static Singleton s;
return s;
}
void my_singleton_cool_function()
{
std::lock_guard<std::mutex> lg(my_mutex_member);
// cool code here
}
};
In the above example lg will lock the mutex and at the end of the function, when lg gets destroyed the destructor will unlock the mutex. This means only one thread can run the function at the same time. This allows all the threads to have a reference to the singleton, and will only block if two or more threads try to do the same thing at the same time.
My question is how can I ensure that only one thread is using the instance at a particular time.
As a general rule, you can't.
Nathan Oliver's answer works in the special case where the only way for other modules to "use the instance" is by calling it's methods. In that case, you can ensure that every one of those methods locks the same mutex.
But, if your singleton exposes any public data member, then all bets are off: You will not have any way to control how other modules "use" your object's public data members.
Beware! Even if you make all of the data members private, and make the singleton object really, truly "thread safe;" that still does not guarantee the thread safety of other code that might depend on some relationship between your singleton object and some other data.
Thread safety isn't really about ensuring that "only one thread uses the object at a time." Thread safety is about preserving invariant relationships. For example, if you have a doubly-linked ring data structure, then an important invariant is, p->next->prev must always be equal to p.
A thread that wants to splice a new element into the ring must temporarily break the invariant. "Thread safety" in that case means ensuring that no other thread will be able to see the temporarily broken state.
Building a program out of "thread safe" objects doesn't make the whole program "thread safe", because the higher level program can depend on important invariant relationships between the objects. And, even though the objects are individually threads safe, there is no way for them to be aware of the higher-level relationships that are meaningful to the program as a whole.
(Code taken from book: http://gameprogrammingpatterns.com/ by Robert Nystrom)
In the book above the author comes with two different ways of making a singleton class:
First one:
class FileSystem
{
public:
static FileSystem& instance()
{
// Lazy initialize.
if (instance_ == NULL) instance_ = new FileSystem();
return *instance_;
}
private:
FileSystem() {}
static FileSystem* instance_;
};
And second one:
class FileSystem
{
public:
static FileSystem& instance()
{
static FileSystem *instance = new FileSystem();
return *instance;
}
private:
FileSystem() {}
};
Later he states that the second one is more proper way to do this, since it is thread safe, while the first one is not.
What makes the second one thread safe?
What is the difference in static declarations between these two?
The first version is not thread-safe for multiple threads may try to read and modify instance_ concurrently without any synchronization, which leads to a race condition.
The second version is thread-safe since C++11. Quoted from cppreference (the Static local variables section):
If multiple threads attempt to initialize the same static local
variable concurrently, the initialization occurs exactly once (similar
behavior can be obtained for arbitrary functions with std::call_once)
With this guarantee, modification to instance happens only once, and there is no problem with concurrent reads.
Still, the second version is not thread-safe until C++11.
In the first code snippet setting the instance_ pointer to a singleton is an assignment. It does not get any special treatment from the compiler. In particular, it could be done multiple times if instance() is invoked from concurrent threads.
This creates a problem when two concurrent threads try evaluating instance_ == NULL, and get a true. At this point both threads create a new instance, and assign it to the instance_ variable. The first pointer assigned to instance_ is leaked, because the second thread immediately overrides it, rendering the object inaccessible.
In the second code snippet setting the instance pointer is initialization. The compiler guarantees that initialization of a static variable will be done at most once, regardless of the number of threads that invoke instance() concurrently. Essentially, the guarantee that there is at most one singleton in the system is provided by the compiler, without any explicit code for handling concurrency.
In former case, if two threads try to create the instance at the same time, 2 (or more) copies of singleton objects might be created. (if **instance_** is observed NULL by both and both create a new instance). (Even worse, thread creating first instance may get a different value of instance in subsequent calls)
While second one uses static initialization and object is constructed when the function is invoked for the first time. So it is guaranteed by the compiler that static FileSystem *instance = new FileSystem(); would be executed at most once during the lifetime of program single and thus atmist single copy of object would exist at any time.
This makes the later design thread safe for C++11 and onwards complian C++ compilers. Though the design may not be safe for in C++03 and C++98 implementation.
Another downside of former design is, the object can not be destructed while in later design it can be destructed by changing the typeof instance_ to static FileSystem. i.e.
static FileSystem& instance()
{
static FileSystem instance;
return instance;
}
Related: Is Meyers implementation of Singleton pattern thread safe?
I have a state engine that uses a Singleton software design pattern. The state engine can be accessed by multiple threads. The object is initialized from the main thread at program start up and is not designed for Lazy initialization.
My question is, should I make the public static members volatile like this:
class CStateEngine final
{
private:
/* Contains the Singleton object */
static CStateEngine* instance;
protected:
CStateEngine();
public:
static CStateEngine* Instance() volatile; // Returns the Singleton instance
static void DeleteInstance() volatile; // Deletes the Singleton instance
}
The volatile keyword in C++ is NOT the same as in any other languages. In C++ it means that the compiler will make sure that the value is always newly read from memory, and never a cached value is used.
It has it's uses the embedded world and other places. If you wanted to have an always up to date view of a certain variable you'd mark it as volatile.
It has nothing however to do with multithreading.
You should not use a singleton in a multi-threaded environment, because it will be a cause for contention as multiple threads try to access your object. It will cause your programs to lag and it entirely defeats using threads in the first place.
You should pass objects around, and you should be able to create new ones as you need them.
If you can't do that, review your design.
I did find plenty of questions regarding singletons and thread safety, but none that quite answered this question for me... but I apologize if it is a repeat.
If I have a singleton object which will be used by multiple threads, I understand that any mutation to member variables should be carefully considered, but what about variables that are local to a method?
Consider this psuedo-code:
class Singleton [assume this has all the trappings of a proper singleton]
{
int doSomething() {
SomeObject obj;
obj.doStuff();
return obj.result();
}
}
In this case, is the local 'obj' thread safe? Does each thread get its own copy of it, even though there is only one object of the Singleton class?
Yes, obj is unique per thread.
There could be threading issues however if it accessed & modified common data - for example doStuff or result accesses a static member of SomeObject or some global.
As Luchian said you are fine so far, however, if you have a static or any & or * variable, then try to use a mutex lock or a spin lock. Mutex locks and spin locks exist in all unix based systems, and I think you can use them in windows as well, but you need first to add them somehow.
Here is a link for pthread mutexes: http://www.thegeekstuff.com/2012/05/c-mutex-examples/
And here another one for windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686927(v=vs.85).aspx
I would like to create a singleton class that is instantiated once in each thread where it is used. I would like to store the instance pointers in TLS slots. I have come up with the following solution but I am not sure whether there are any special considerations with multithreaded access to the singelton factory when thread local storage is involved. Maybe there is also a better solution to implement thread local singletons.
class ThreadLocalSingleton
{
static DWORD tlsIndex;
public:
static ThreadLocalSingleton *getInstance()
{
ThreadLocalSingleton *instance =
static_cast<ThreadLocalSingleton*>(TlsGetValue(tlsIndex));
if (!instance) {
instance = new ThreadLocalSingleton();
TlsSetValue(tlsIndex, instance);
}
return instance;
}
};
DWORD ThreadLocalSingleton::tlsIndex = TlsAlloc();
The Tls*-functions are of course win32 specific but portability is not the main issue here. Your thoughts concerning other platforms would still be valuable.
Major Edit: I had originally asked about using double-checked locking in this scenario. However as DavidK pointed out, the singletons are to be created on a per thread basis anyway.
The two remaining questions are:
is it appropriate to reply on TlsGetValue/TlsSetValue to ensure that each thread gets one instance and that the instance is created only once for each thread?
Is it possible to register a callback that allows me to clean up an instance that was associated with a particular thread when that thread finishes?
Since your objects are thread-local, why do you need locking to protect them at all? Each threads that calls getInstance() will be independent of any other thread, so why not just check that the singleton exists and create it if needed? The locking would only be needed if multiple threads tried to access the same singleton, which isn't possible in your design as it is above.
EDIT: Moving on to the two other questions... I can't see any reason why using TlsAlloc/TlsGetValue etc. wouldn't work as you'd expect. Since the memory holding the pointer to your singleton is only accessible to the relevant thread, there won't be any problems with a lazy initialization of it. However there's no explicit callback interface to clean them up.
The obvious solution to that would be to have a method that is called by all your thread main functions that clears up the created singleton, if any.
If it's very likely that the thread will create a singelton, a simpler pattern might be to create the singleton at the start of the thread main function and delete it at the end. You could then use RAII by either creating the singleton on the stack, or holding it in a std::auto_ptr<>, so that it gets deleted when the thread ends. (Unless the thread terminates abnormally, but if that happens all bets are off and a leaked object is the least of your problems.) You could then just pass the singleton around, or store it in TLS, or store it in a member of a class, if most of the thread functionality is in one class.
Have a look at this paper to understand why double-checked locking doesn't work in general (even though it might work in special cases).
We use a class that stores a map of thread id to data to implement our thread local storage. This seems to work very well, then an instance of this class can be placed anywhere you require thread local storage. Normally clients use an instance of as a static private field.
Here is a rough outline of the code
template <class T>
struct ThreadLocal {
T & value()
{
LockGuard<CriticalSection> lock(m_cs);
std::map<int, T>::iterator itr = m_threadMap.find(Thread::getThreadID());
if(itr != m_threadMap.end())
return itr->second;
return m_threadMap.insert(
std::map<int, T>::value_type(BWThread::getThreadID(), T()))
.first->second;
}
CriticalSection m_cs;
std::map<int, T> m_threadMap;
};
This is then used as
class A {
// ...
void doStuff();
private:
static ThreadLocal<Foo> threadLocalFoo;
};
ThreadLocal<Foo> A::threadLocalFoo;
void A::doStuff() {
// ...
threadLocalFoo.value().bar();
// ...
}
This is simple and works on any platform where you can get the thread id. Note the Critical Section is only used to return/create the reference, once you have the reference all calls are outside the critical section.