SimpleRandomizer: Use std::random

pull/135/merge
Tatsuhiro Tsujikawa 2013-09-28 22:00:37 +09:00
parent 44479c910e
commit 986f69e5bf
3 changed files with 29 additions and 18 deletions

View File

@ -161,7 +161,7 @@ Context::Context(bool standalone,
throw DL_ABORT_EX("Option processing failed");
}
}
SimpleRandomizer::init();
SimpleRandomizer::getInstance()->init();
#ifdef ENABLE_BITTORRENT
bittorrent::generateStaticPeerId(op->get(PREF_PEER_ID_PREFIX));
#endif // ENABLE_BITTORRENT

View File

@ -38,6 +38,7 @@
#include <unistd.h>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include "a2time.h"
@ -56,7 +57,8 @@ const std::unique_ptr<SimpleRandomizer>& SimpleRandomizer::getInstance()
void SimpleRandomizer::init()
{
#ifndef __MINGW32__
srandom(time(nullptr)^getpid());
// Just in case std::random_device() is fixed, add time and pid too.
eng_.seed(std::random_device()()^time(nullptr)^getpid());
#endif // !__MINGW32__
}
@ -90,7 +92,7 @@ long int SimpleRandomizer::getRandomNumber()
}
return val;
#else // !__MINGW32__
return random();
return eng_();
#endif // !__MINGW32__
}
@ -99,15 +101,18 @@ long int SimpleRandomizer::getMaxRandomNumber()
#ifdef __MINGW32__
return INT32_MAX;
#else // !__MINGW32__
// TODO Warning: The maximum value of random() in some sytems (e.g.,
// Solaris and openbsd) is (2**31)-1.
return RAND_MAX;
return eng_.max();
#endif // !__MINGW32__
}
long int SimpleRandomizer::getRandomNumber(long int to)
{
assert(to > 0);
#ifdef __MINGW32__
return getRandomNumber() % to;
#else // !__MINGW32__
return std::uniform_int_distribution<long int>(0, to - 1)(eng_);
#endif // !__MINGW32__
}
long int SimpleRandomizer::operator()(long int to)
@ -122,16 +127,19 @@ void SimpleRandomizer::getRandomBytes(unsigned char *buf, size_t len)
throw std::bad_alloc();
}
#else
while (len) {
// If RAND_MAX is less than 2**16-1, we are in trouble.
union {
uint16_t r;
uint8_t b[2];
} r = { (uint16_t)(random() & 0xffffu) };
for (auto i = 0; i < 2 && len; ++i, --len) {
*buf++ = r.b[i];
}
uint32_t val;
size_t q = len / sizeof(val);
size_t r = len % sizeof(val);
auto gen = std::bind(std::uniform_int_distribution<uint32_t>
(0, std::numeric_limits<uint32_t>::max()),
eng_);
for(; q > 0; --q) {
val = gen();
memcpy(buf, &val, sizeof(val));
buf += sizeof(val);
}
val = gen();
memcpy(buf, &val, r);
#endif
}

View File

@ -38,6 +38,7 @@
#include "Randomizer.h"
#include <memory>
#include <random>
#ifdef __MINGW32__
# include <wincrypt.h>
@ -51,17 +52,19 @@ private:
#ifdef __MINGW32__
HCRYPTPROV cryProvider_;
#endif //__MINGW32__
#else // !__MINGW32__
std::minstd_rand eng_;
#endif //!__MINGW32__
SimpleRandomizer();
public:
static const std::unique_ptr<SimpleRandomizer>& getInstance();
static void init();
virtual ~SimpleRandomizer();
void init();
virtual long int getRandomNumber() CXX11_OVERRIDE;
virtual long int getMaxRandomNumber() CXX11_OVERRIDE;