Boost logo

Boost :

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]>
> wrote:
>
>> 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