[Development] websockets (was RE: Qt 5.3 Feature freeze is coming quite soon...)
Olivier Goffart
olivier at woboq.com
Sun Feb 9 23:57:24 CET 2014
On Sunday 09 February 2014 22:40:22 Kurt Pattyn wrote:
> If I use std::random as Thiago proposed (see
> http://en.cppreference.com/w/cpp/numeric/random), like:
>
> //one time initialisation
> Q_CONST_EXPR std::size_t numSeeds = 13; //arbitrary number
> quint32 seeds[numSeeds] = { 0 };
> bool success = false;
>
> try {
> std::random_device seeder; //supported since MSVS 2008, since
GCC
> 4.5 if (seeder.entropy() >= 0.5) {
> std::generate_n(seeds, numSeeds, seeder);
> success = true;
> }
> } catch (const std::exception &) {
> //fall through
> }
> #ifdef Q_OS_WIN //the MinGW implementation of GCC 4.8 has a known bug in
> std::random_device if (!success) {
> HCRYPTPROV hp = 0;
> BYTE rb[4];
> if ((success = CryptAcquireContext(&hp, 0, 0, PROV_RSA_FULL,
> CRYPT_VERIFYCONTEXT)) == TRUE) for (std::size_t i = 0; i < numSeeds; ++i) {
> if ((success = CryptGenRandom(hp, sizeof(quint32), seeds +
> i) != TRUE) break;
> }
> CryptReleaseContext(hp, 0);
> }
> #endif
> if (!success) {
> qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
> for (std::size_t i = 0; i < numSeeds; ++i) {
> const qreal multiplier =
> qreal(std::numeric_limits<quint8>::max()) / qreal(RAND_MAX); const quint32
> byte1 = quint32(qrand() * multiplier) & 0xFF; const quint32 byte2 =
> quint32(qrand() * multiplier) & 0xFF; const quint32 byte3 = quint32(qrand()
> * multiplier) & 0xFF; const quint32 byte4 = quint32(qrand() * multiplier) &
> 0xFF; seeds[i] = byte1 | byte2 << 8 | byte3 << 16 | byte4 << 24; }
> }
>
> std::seek_seq seedSequence(seeds, seeds + numSeeds);
> std::mt19937 randomiser(seedSequence);
> //std::uniform_int_distribution<std::uint32_t> dist; //range from 0 to
> UINT_MAX
>
>
> //somewhere else
> return randomiser(); //no need to use a distribution function as mt19937
> outputs 2^32
>
>
> Would this already be more acceptable?
> Of course, this implementation requires C++11 support.
> An interesting presentation about std::random can be found here:
> http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
>
> If the above implementation suffices, then a virtual method would not be
> needed anymore.
>
> Should I fall back to the ordinary qrand() when the other methods fail?
>
I think you are making it more complicated than it need to be.
qrand has maximum 32bit entropy (because it uses rand_r internally which only
has 32 bit state), therefore calling it several time in a row is totally
useless and don't add entropy.
It turns out 32 bit entropy is enough because that's the size of your mask, so
just use qrand with a decent proper seed:
#if has_std_randrom_device
return qsrand(std::random_device()());
#else
static QElapsedTimer t;
return qsrand(t.nsecsElapsed());
#endif
--
Olivier
Woboq - Qt services and support - http://woboq.com - http://code.woboq.org
More information about the Development
mailing list