From: Andy (atompkins_at_[hidden])
Date: 2007-05-07 10:56:03


Matthias Troyer <troyer_at_[hidden]> wrote in
news:F45D2822-2671-4B1B-B930-3A56E9CEF1C5_at_[hidden]:

>
> On 6 May 2007, at 14:37, Peter Dimov wrote:
>
>> Matthias Troyer wrote:
>>> On 5 May 2007, at 06:16, Peter Dimov wrote:
>>>> * I agree that the time(0) seed is unacceptable. A good source of
>>>> entropy
>>>> probably deserves its own library. It's also not easy to make it
>>>> header-only. One compromise could be for the create function to
>>>> take an
>>>> Engine argument, but this takes away the simplicity.
>>>
>>> How about just adding an additional create function that takes an
>>> engine?
>>
>> The existing create function is dangerous as it doesn't generate
>> reasonably
>> unique identifiers. We can't fix that by adding more overloads.
>
> I fully agree that it is very dangerous, especially on parallel
> machines. However, in addition to fixing this, it would be good to
> have the engine be customizable.
>
> Matthias

I agree that the create function needs improvement. It suffers from
threading problems (because of static variables) and from a hard coded
random number generator (also a hard coded seed).

My solution is to create a generator class, as follows:

// maybe a better name
// maybe a different default random number generator
template <typename UniformRandomNumberGenerator = boost::mt19937>
class random_guid_generator : boost::noncopyable
{
  typedef boost::uniform_int<uint8_t> DistributionType;
public:
  explicit random_guid_generator(UniformRandomNumberGenerator& engine
    = boost::mt19937(time(0)))
    : engine_(engine)
    , generator_(engine_, DistributionType(0, 255))
  {}

  guid create()
  {
    guid g;
    // create guid using generator_()
    return g;
  }

private:
  UniformRandomNumberGenerator& engine_;
  boost::variate_generator<UniformRandomNumberGenerator&,
    DistributionType> generator_;
};

to be used like:

random_guid_generator<> guid_gen;
guid g = guid_gen.create();

or:

uint32_t seed = 0; // get good seed
boost::lagged_fibonacci44497 engine(seed);
random_guid_generator<boost::lagged_fibonacci44497> guid_gen(engine);
guid g = guid_gen.create();

or:

boost::random_device engine;
random_guid_generator<boost::random_device> guid_gen(engine);
guid g = guid_gen.create();

One could have a random_guid_generator per thread/processor/... solving
the threading problems. Also one can provide any random number
generator that satisfies the Uniform Random Number Generator concept
from the Boost.Random library.

Andy.