#include <atomic>
#include <unistd.h>
#include <sys/time.h>
+#include <random>
+#include <array>
+
+#if __GNUC_PREREQ(4, 8)
+#include <ext/random>
+#define USE_SIMD_PRNG
+#endif
namespace folly {
uint32_t randomNumberSeed() {
struct timeval tv;
- gettimeofday(&tv, NULL);
+ gettimeofday(&tv, nullptr);
const uint32_t kPrime0 = 51551;
const uint32_t kPrime1 = 61631;
const uint32_t kPrime2 = 64997;
+ kPrime3 * static_cast<uint32_t>(tv.tv_usec);
}
+
+folly::ThreadLocalPtr<ThreadLocalPRNG::LocalInstancePRNG>
+ThreadLocalPRNG::localInstance;
+
+class ThreadLocalPRNG::LocalInstancePRNG {
+#ifdef USE_SIMD_PRNG
+ typedef __gnu_cxx::sfmt19937 RNG;
+#else
+ typedef std::mt19937 RNG;
+#endif
+
+ static RNG makeRng() {
+ std::array<int, RNG::state_size> seed_data;
+ std::random_device r;
+ std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
+ std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
+ return RNG(seq);
+ }
+
+ public:
+ LocalInstancePRNG() : rng(std::move(makeRng())) {}
+
+ RNG rng;
+};
+
+ThreadLocalPRNG::LocalInstancePRNG* ThreadLocalPRNG::initLocal() {
+ auto ret = new LocalInstancePRNG;
+ localInstance.reset(ret);
+ return ret;
+}
+
+uint32_t ThreadLocalPRNG::getImpl(LocalInstancePRNG* local) {
+ return local->rng();
+}
+
}