Make builtin_random thread safe

This commit is contained in:
ridiculousfish 2019-04-28 15:13:30 -07:00
parent f66e010949
commit 3d63a68dd0

View file

@ -15,6 +15,17 @@
#include "io.h" #include "io.h"
#include "wutil.h" // IWYU pragma: keep #include "wutil.h" // IWYU pragma: keep
/// \return a random-seeded engine.
static std::minstd_rand get_seeded_engine() {
std::minstd_rand engine;
// seed engine with 2*32 bits of random data
// for the 64 bits of internal state of minstd_rand
std::random_device rd;
std::seed_seq seed{rd(), rd()};
engine.seed(seed);
return engine;
}
/// The random builtin generates random numbers. /// The random builtin generates random numbers.
int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) { int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
wchar_t *cmd = argv[0]; wchar_t *cmd = argv[0];
@ -30,16 +41,10 @@ int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
return STATUS_CMD_OK; return STATUS_CMD_OK;
} }
static bool seeded = false; // We have a single engine which we lazily seed. Lock it here.
static std::minstd_rand engine; static owning_lock<std::minstd_rand> s_engine{get_seeded_engine()};
if (!seeded) { auto engine_lock = s_engine.acquire();
// seed engine with 2*32 bits of random data std::minstd_rand &engine = *engine_lock;
// for the 64 bits of internal state of minstd_rand
std::random_device rd;
std::seed_seq seed{rd(), rd()};
engine.seed(seed);
seeded = true;
}
int arg_count = argc - optind; int arg_count = argc - optind;
long long start, end; long long start, end;