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"); throw DL_ABORT_EX("Option processing failed");
} }
} }
SimpleRandomizer::init(); SimpleRandomizer::getInstance()->init();
#ifdef ENABLE_BITTORRENT #ifdef ENABLE_BITTORRENT
bittorrent::generateStaticPeerId(op->get(PREF_PEER_ID_PREFIX)); bittorrent::generateStaticPeerId(op->get(PREF_PEER_ID_PREFIX));
#endif // ENABLE_BITTORRENT #endif // ENABLE_BITTORRENT

View File

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

View File

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