@@ -23,16 +23,26 @@ else # !windows
2323 rand (rd:: RandomDevice , sp:: SamplerBoolBitInteger ) = read (getfile (rd), sp[])
2424 rand (rd:: RandomDevice , :: SamplerType{Bool} ) = read (getfile (rd), UInt8) % Bool
2525
26- function getfile (rd:: RandomDevice )
27- devrandom = rd. unlimited ? DEV_URANDOM : DEV_RANDOM
28- # TODO : there is a data-race, this can leak up to nthreads() copies of the file descriptors,
29- # so use a "thread-once" utility once available
30- isassigned (devrandom) || (devrandom[] = open (rd. unlimited ? " /dev/urandom" : " /dev/random" ))
31- devrandom[]
26+ mutable struct FileRef
27+ @atomic file:: Union{IOStream, Nothing}
3228 end
3329
34- const DEV_RANDOM = Ref {IOStream} ()
35- const DEV_URANDOM = Ref {IOStream} ()
30+ const DEV_RANDOM = FileRef (nothing )
31+ const DEV_URANDOM = FileRef (nothing )
32+
33+ function getfile (rd:: RandomDevice )
34+ ref = rd. unlimited ? DEV_URANDOM : DEV_RANDOM
35+ fd = ref. file
36+ if fd === nothing
37+ fd = open (rd. unlimited ? " /dev/urandom" : " /dev/random" )
38+ old, ok = @atomicreplace ref. file nothing => fd
39+ if ! ok
40+ close (fd)
41+ fd = old:: IOStream
42+ end
43+ end
44+ return fd
45+ end
3646
3747end # os-test
3848
@@ -411,6 +421,10 @@ for T in BitInteger_types
411421end
412422
413423function __init__ ()
424+ @static if ! Sys. iswindows ()
425+ @atomic DEV_RANDOM. file = nothing
426+ @atomic DEV_URANDOM. file = nothing
427+ end
414428 seed! (GLOBAL_RNG)
415429end
416430
0 commit comments