Re: [Boost-users] thread safety of the mutex ctor
Are you sure there are no guarantees for function scope statics?
I think the following is thread safe:
void
my_func()
{
static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&m);
// do something once
pthread_mutex_unlock(&m);
}
because the C-style PTHREAD_MUTEX_INITIALIZER doesn't involve a constructor call: the static is initialised before _any_ threads are running.
Also, constructors of global statics are not guaranteed to be single-threaded for the same reason you can't safely reference one static from the constructor of another (The Static Initialisation Order Fiasco); one constructor could create a thread that goes and uses an uninitialised static, whilst the main thread tries to initialise it.
Do you know whether the mutex ctor is thread-safe?
T. Scott Urban
On Thu, 2005-08-18 at 06:22 +1000, Christopher Hunt wrote: > On 18/08/2005, at 1:19 AM, boost-users-request@lists.boost.org wrote: > > > I envisage two threads accessing a function like this concurrently: > > > > template<typename T> > > boost::shared_ptr<T> > > my_func() > > { > > static boost::mutex m; > > boost::mutex::scoped_lock l(m); > > > > static boost::shared_ptr<T> p(new T); > > return p; > > } > > > > and my worry is that both threads could attempt to do the static > > initialisation of m concurrently. Is there protection against this?
> > Is it even possible to protect against this? > The scope of m is actually outside of your function given that it is > static. Thus it will be initialised outside of your function generally > before any other threads get to start up.
The scope of m is in the function, not global, but it has static duration. Unlike a global, m will only be constructed if my_func() is ever called in your program.
That should set of warning bells in you brain.
I don't believe there are any guarantees about the thread safety of the initialization of function scope statics. This applies not just to the mutex class in question but any type. A particular compiler might make this usage thread safe - or maybe only guarantee initialization of basic types - but I don't know if it's covered by the pthread spec - and that's not helpful anyway to boost users, in general. And of course, the C++ standard is as usual silent on the matter.
You can make the mutex global - anonymous namespace or whatever. Since global initializations are single threaded, you trade the threading problem for the loss of on-demand resource usage.
Another way to deal with this kind of problem is to use a modified singleton pattern, but to make that thread safe, you need another mutex (unless you want to risk DCL), so seems kind of pointless for this instance.
-- t. scott urban <scottu@apptechsys.com>
-- James E Taylor james@onalog.net ___________________________________ NOCC, http://nocc.sourceforge.net
On Thu, 2005-08-18 at 11:22 +0000, James E Taylor wrote:
Are you sure there are no guarantees for function scope statics?
I think the following is thread safe:
void my_func() { static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&m); // do something once pthread_mutex_unlock(&m); }
because the C-style PTHREAD_MUTEX_INITIALIZER doesn't involve a constructor call: the static is initialised before _any_ threads are running.
Also, constructors of global statics are not guaranteed to be single-threaded for the same reason you can't safely reference one static from the constructor of another (The Static Initialisation Order Fiasco); one constructor could create a thread that goes and uses an uninitialised static, whilst the main thread tries to initialise it.
Do you know whether the mutex ctor is thread-safe?
Well, like I said, I think this is all undefined or at least
implementation dependent. This is what my pthread docs say about the
above code, though:
man pthread_mutex_init:
Without static initialization, a self-initializing routine foo() might
look as follows:
static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
static pthread_mutex_t foo_mutex;
void foo_init()
{
pthread_mutex_init(&foo_mutex, NULL);
}
void foo()
{
pthread_once(&foo_once, foo_init);
pthread_mutex_lock(&foo_mutex);
/* Do work. */
pthread_mutex_unlock(&foo_mutex);
}
With static initialization, the same routine could be coded as follows:
static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
void foo()
{
pthread_mutex_lock(&foo_mutex);
/* Do work. */
pthread_mutex_unlock(&foo_mutex);
}
....
End quote
--
t. scott urban
participants (2)
-
James E Taylor
-
t. scott urban