Re: question re. usage of "static" within static member functions of a class
"James Kanze" <james.kanze@gmail.com> wrote in message
news:f0ed97f9-ea04-4952-88f2-a1982725a0b4@38g2000yqr.googlegroups.com...
On Sep 7, 7:24 am, "Chris M. Thomasson" <n...@spam.invalid> wrote:
"ssb" <s.sharm...@gmail.com> wrote in message
news:97dc452a-f6a5-4a77-9a9c-ea8491d37e40@e4g2000prn.googlegroups.com...
During a code review, I found the following lines of code:
[...]
The "instance" method was implemented as follows:
Data* Data::instance()
{
static Data* model = new Data();
return model;
}
I have never come across a situation where a pointer was set
to static in such a case. Is this valid?
It's a singleton.
And to answer the question, it's perfectly valid. A pointer is
an object, just like any other variable, and obeys the same
rules as other variables.
What are the potential pitfalls in such programming practices?
The storage that `model' points to will never be destroyed,
also it's not thread-safe.
Not being destroyed is presumably the reason the code is written
this way. Most of the time, you don't want a singleton to be
destructed. In other word, it's a feature designed to avoid
pitfalls. As for thread-safety, it depends on the
implementation, it is thread safe---modulo bugs---in g++. (But
you're probably right for most implementations.)
You can get around static initialization and destruction ordering issues by
using a strongly thread-safe smart pointer to manage the singleton. The
pseudo-code would be something like the following pseudo-code:
_____________________________________________________________________
template<typename T>
static local_ptr<T>
once()
{
static global_ptr<T> g_instance;
local_ptr<T> lptr(g_instance);
if (! lptr)
{
static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&g_mutex);
lptr = g_instance;
if (! lptr)
{
try
{
lptr.reset(new T());
}
catch (...)
{
pthread_mutex_unlock(&g_mutex);
throw;
}
g_instance = lptr;
}
pthread_mutex_unlock(&g_mutex);
}
return lptr;
}
_____________________________________________________________________
This is strongly thread-safe and will always work no matter how the static
ctor/dtor ordering comes out. The caveat, well, it's definitely not as
efficient as using a raw pointer and explicitly leaking the singleton.