
Edouard A. wrote:
On Fri, 09 Jan 2009 03:48:05 -0600, Michael Marcin <mike.marcin@gmail.com> 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