Fleet  0.0.9
Inference in the LOT
Rng.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <thread>
4 #include <mutex>
5 
6 #include <sys/syscall.h>
7 #include <sys/random.h>
8 
17 thread_local class Rng : public std::mt19937 {
18 public:
19 
20  // The first of these that is made is called the "base" and is used to seed any others.
21  // Because this variable rng is thread_local, each thread will get its own and its seed
22  // will be determined (deterministically) from base.
23  static std::mutex mymut;
24  static Rng* base;
25 
26  Rng() : std::mt19937() {
27 
28  // allow only one constructor at a time since we need to set the base seed
29  std::lock_guard guard(mymut);
30 
31  if(base == nullptr) {
32  // on construction we initialize from /dev/urandom
33  std::array<unsigned long, std::mt19937::state_size> state;
34  sysrandom(state.begin(), state.size()*sizeof(unsigned long));
35  std::seed_seq seedseq(state.begin(), state.end());
36  this->std::mt19937::seed(seedseq);
37 
38  base = this;
39  }
40  else {
41  randomize();
42  }
43  }
44 
45  void randomize() {
46  // seed from base with random numbers.
47  // This will get us replicable numbers assuming the
48  // order of construction is fixed
49  std::array<unsigned long, std::mt19937::state_size> state;
50  for(size_t i=0;i<state.size();i++){
51  state[i] = base->operator()();
52  }
53  std::seed_seq seedseq(state.begin(), state.end());
54  this->std::mt19937::seed(seedseq);
55  }
56 
60  void seed(unsigned long s) {
61  if(s != 0) {
62  this->std::mt19937::seed(s);
63  }
64  }
65 
66  static size_t sysrandom(void* dst, size_t dstlen) {
67  // from https://stackoverflow.com/questions/45069219/how-to-succinctly-portably-and-thoroughly-seed-the-mt19937-prng
68  char* buffer = reinterpret_cast<char*>(dst);
69  std::ifstream stream("/dev/urandom", std::ios_base::binary | std::ios_base::in);
70  stream.read(buffer, dstlen);
71  return dstlen;
72  }
73 
74 
75 } DefaultRNG;
76 
77 std::mutex Rng::mymut;
78 Rng* Rng::base = nullptr;
Definition: Rng.h:17
Rng DefaultRNG
Rng()
Definition: Rng.h:26
void randomize()
Definition: Rng.h:45
void seed(unsigned long s)
Seed only if s is nonzero.
Definition: Rng.h:60
static std::mutex mymut
Definition: Rng.h:23
static size_t sysrandom(void *dst, size_t dstlen)
Definition: Rng.h:66
static Rng * base
Definition: Rng.h:24