Boost logo

Boost Users :

From: Christopher Hunt (huntc_at_[hidden])
Date: 2005-08-18 19:22:52


On 18/08/2005, at 8:04 AM, boost-users-request_at_[hidden] wrote:

> On 8/17/05, Christopher Hunt <huntc_at_[hidden]> wrote:
>> On 18/08/2005, at 1:19 AM, boost-users-request_at_[hidden] 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.
>
> This does not sound right to me, so I whipped up a test case... on
> HP-UX, given the code:
Sorry, I should have looked at the problem more closely - you're right
to be suspicious of course. Stroustrup is actually pretty clear on this
too, "It will be initialized only the first time the thread of
execution reaches its definition". Whoops - sorry for throwing you off.

Using the Singleton Design Pattern, I have a static mutex in my class
covering the static instance member. Given their static member nature,
they get initialised during process startup. Again Stroustrup confirms
this with, "A variable defined outside any function (that is, global,
namespace, and *class static variables*) is initialized (constructed)
before main() is invoked,...".

In case it helps, here's something that I knocked together (and tested)
using the boost library. The class implements the Singleton design
pattern safely and is also more robust from an exception handling
perspective (note: this is the first time I've used boost threads - I'm
actually using another thread class library...):

*****
#include <stdexcept>
#include <boost/thread/mutex.hpp>

// Modified Singleton class from Gamma et. al. Returns
// a reference to the instance instead of a pointer
// recognising the use of exceptions. Additionally,
// the instance is guaranteed to be allocated in a
// thread safe manner.

class Singleton
{
   public:

     static Singleton& Instance() throw(std::bad_alloc);

   protected:

     Singleton() throw(std::bad_alloc);

   private:

     static Singleton* mInstanceP;
     static boost::mutex mInstancePMutex;

};

// Implementation

using namespace boost;
using namespace std;

Singleton* Singleton::mInstanceP = 0;
mutex Singleton::mInstancePMutex;

Singleton& Singleton::Instance() throw(bad_alloc)
{
     boost::mutex::scoped_lock theInstancePMutexLock(mInstancePMutex);

     if (mInstanceP == 0)
         mInstanceP = new Singleton();

     return *mInstanceP;
}

Singleton::Singleton() throw(bad_alloc)
{}

int main (int argc, char * const argv[])
{
     try
     {
         Singleton& theSingleton = Singleton::Instance();
             // Guaranteed thread safe.
     }
     catch (const bad_alloc&)
     {}

     return 0;
}
*****

'hope that this is useful.

Cheers,
-C


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net