/* @file random_seed.hpp */ #include #include #include #ifdef _BSD_SOURCE # include #else # include #endif namespace xo { namespace rng { /* generate a 64-bit random seed using /dev/urandom or similar source. * This is relatively expensive; at least cost of a system call * + may block if host has rebooted recently * * Require: * - T is null-constructible. * * return value will contain a T-instance in which representation * has been populated with random bits. Expecting T to be something * like int32_t, or std::array */ template void random_seed(T * p_seed) { # ifdef _BSD_SOURCE /* NOTE: arc4random_buf() works on darwin/nix; * probably need to do something else on intel linux */ ::arc4random_buf(p_seed, sizeof(*p_seed)); # else /* avail flags: GRND_RANDOM | GRND_NONBLOCK */ while (::getrandom(p_seed, sizeof(*p_seed), 0) == -1) { if (errno == EINTR) { /* interrupted by signal, try again */ continue; } else { break; } } # endif } /*random_seed*/ template T random_seed() { T retval; random_seed(&retval); return retval; } /*random_seed*/ /* RAII-style random-number seed * * Usage: * * Seed seed; * * auto eng = xoshiro256ss(seed); * or * auto rng = UnitIntervalGen::make(seed); */ template struct Seed { using seed_type = typename Engine::seed_type; Seed() { random_seed(&seed_); } operator seed_type const & () const { return seed_; } seed_type seed_; }; /*Seed*/ template inline std::ostream & operator<<(std::ostream & os, Seed const & x) { os << x.seed_; return os; } /*operator<<*/ } /*namespace rng*/ } /*namespace xo*/ /* end random_seed.hpp */