So my concern is hitting a function which creates a thread before main()
gets called. At that point, thread safe functions need to have a mutex which is ready. Only, there is no way to guarantee the order in which global objects get initialized in C++ (well, to some extend, we can, but still, in a large project, good luck with that!)
So I like to have my global objects, such as singletons, allocated at runtime. That way, they get initialized the first time you call their instance()
function and that means they are ready when needed. However, if I have two or more threads running, they may each end up creating an instance unless I make sure to have a valid lock in that function.
I want to make sure that using the following initialization:
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
always happen at compile time and thus that global_mutex
is always going to be ready for pthread_mutex_lock()
.
This means my singleton (and other classes that need initialization before main()
gets called) can rely on that mutex as in the following simplified code:
// singleton.h
class singleton
{
public:
static singleton * instance();
...other functions...
private:
singleton();
};
// singleton.cpp
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
singleton * global_singleton = nullptr;
singleton::singleton()
{
// do some initialization
}
singleton * singleton::instance()
{
pthread_mutex_lock(&global_mutex); // <- works even before main() called?
if(global_singleton == nullptr)
{
global_singleton = new singleton();
}
pthread_mutex_unlock(&global_mutex);
return global_singleton;
}
Note: I'm not asking about the validity of the singleton pattern. Just about the mutex. Also, no, you can't safely use a smart pointer in the global variable because you can't know whether it will be initialized before you call the instance()
function. If you want to return a smart pointer, you can always use a bare pointer to a smart pointer. It doesn't change much anything for the singleton. It still won't get destroyed automatically.