The default implementation of random_device uses /dev/urandom, which may not be available to systems like bare-metals.
This patch adds a CMake option "LIBCXX_ENABLE_RANDOM_DEVICE" to control the build. Default is On.
I keep seeing patches go by for other targets where they're just implementing random_device for their target. It doesn't *have* to be based on an actual /dev/urandom. You can see all the other options under #ifdefs in this file: getentropy, /dev/random, nacl_secure_random, arc4random, rand_s,... If you're on a target that doesn't have any of these, then IMO the appropriate patch would be one of
where the latter provides a "random_device" that yields nothing but zeroes. That would still be very slightly better than providing a non-conforming implementation. (And notice that the useless double random_device::entropy() method will for the first time return a *mathematically correct* value for the always-zero random_device! ;))
@weimingz: Since your platform supports srand(0), is it possible to look at how your platform implements srand(0) and "inline" that implementation into random_device? That seems like it would be more in keeping with the other ifdefs in this file.
I'm confident that constructing an instance of random_device MUST NOT actually call srand. (I'd like to say that it shouldn't even call rand.) Either of those calls would be observable by the programmer. But there is a precedent for e.g. random_shuffle making calls to rand.
We can wrap the random_device as a minstd_rand, a linear congruential enginer that a lot of C lib uses for rand().
However based on documentation, we should just provides dummy implementation which throws an exception in the constructor of random_device [1,2]
But compared with run-time exception, a link time error is better if we simply skip the implementation. Any thoughts?
explicit random_device(const string& token = implementation-defined );
Throws: A value of an implementation-defined type derived from exception if the random_device could not be initialized.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4659.pdf section 29.6.6 Class random_device (page 1082)
Notice that random devices may not always be available to produce random numbers (and in some systems, they may even never be available). This is signaled by throwing an exception derived from the standard exception or when a number is requested with operator()
Disable tests that depend on random_device.
filesystem tests rely on random_device as seed to create random path. Although it's possible to avoid the random_device but if the build target has no random_device, it's very possible that neither filesystem nor other seeding device like clock is available.
I think the direction here is OK. Although I really hate allowing bits of libc++ to be "optional". In this case it should be OK, but often it makes the library trickier to maintain -- and these configurations often go untested between releases.
|5 ↗||(On Diff #132089)|
I would rather keep these tests running using a different source for the random seed if possible.
|1 ↗||(On Diff #132089)|
There are only 3 tests under this directory. I would rather mark each one explicitly with // UNSUPPORTED: libcpp-has-no-random-device
|5 ↗||(On Diff #132089)|
Perhaps the random generator could be initialized using std::chrono::system_clock::now().time_since_epoch().count(), which should produce more distinct values that the typical time(NULL) method used to initialize srand.
[rand.device]/2 seems to be the authoritative word here:
If implementation limitations prevent generating nondeterministic random numbers, the implementation may employ a random number engine.
Yes, the standard says you're allowed to throw an exception from the random_device constructor, or use a PRNG with an arbitrary seed, or even just return zeros from operator(). But none of those behaviors are actually useful; the code will compile, but you won't get the expected randomness. So I prefer this solution, even if it isn't strictly standard-compliant.
(I'll post an updated version with the tests fixed soon.)
Get rid of the test changes.
They were broken in multiple ways, and weren't really useful anyway because the targets where you would want to use this can't run the libcxx testsuite anyway (because they don't have an operating system to run the test programs under).
the targets where you would want to use this can't run the libcxx
testsuite anyway (because they don't have an operating system to run the
test programs under).
I used to run libcxx tests for an arm baremetal toolchain I was building
via semihosted QEMU. It was awkward and slow (especially for some of the
std::*_distribution tests), but it worked.
For those that would prefer random device to not exist if it isn't cryptographically secure, please write a wg21 paper. I will gladly review such a paper, and if you need a presenter, then I will present it if I am attending. I won't be at Rapperswil, but I will be at San Diego.
Stated differently, I agree with both Marshall and the other commenters on this page. I don't want busted random_devices to build, AND I want a standards compliant implementation.
To some degree, this overlaps with http://wg21.link/P0829 . That (my) paper does not require random_device to exist in a freestanding environment.