Subject: Re: [boost] [uuids] generating uuids from multiple threads
From: Michael Marcin (mike.marcin_at_[hidden])
Date: 2009-01-09 13:46:20
Edouard A. wrote:
> On Fri, 09 Jan 2009 03:48:05 -0600, Michael Marcin <mike.marcin_at_[hidden]>
>> For one thing this is yet another case where I used a default
>> constructor on a uuid during natural coding and expected it to be cheap
>> but I digress.
>> Do I have to protect the shared generator with a mutex? Should I even be
>> using a shared generator or should I be constructing it on the stack in
>> this function? I don't expect this to be called very often (twice total
>> in our current application) but I want to make sure it is bullet proof
>> since it can potentially be called concurrently.
> A PRNG is stateful, hence concurrent access lead need to be protected, but
> your mutex needs to be static, of course.
> I just had exactly the same need and I did protect it with a mutex. You
> will probably also have the need to do a "init once" for your PRNG.
> I did something like this for the init :
> static boost::hellekalek1995 rng;
> static boost::mutex mutex;
> static volatile bool initialized = false;
> if (!initialized)
> // double checking pattern
> boost::lock_guard<boost::mutex> lock(mutex);
> if (!initialized)
> // do the init
> rng.seed(blah blah blah);
> initialized = true;
I'm not a threading guru but I was under the impression that
double-checked locking pattern is dependent on the compiler and
processor memory model and not portable.
I am guaranteed that my function won't be called before main and no
threads are started before main so I think that gives me some leeway for
an easier solution.
The uuids documentation says:
"The boost::uuids::uuid_generator::operator() function returns a
random-number-based uuid. The default random number generator is
boost::mt19937 from the Boost Random library. It is seeded with a SHA-1
hash of a number of different values including std::time(0),
std::clock(), uninitialized data, value return from new unsigned int, etc.."
I'm not sure if this means I can expect to create a uuid_generator on
the stack and get a uuid A and then create a uuid_generator on the stack
and get uuid A != B. It seems to be that if somehow thread id or
processor id was also used to create the seed the value I could do this
and avoid any shared state and locking.
-- Michael Marcin
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk