diff --git a/vlib/rand/mt19937/mt19937.v b/vlib/rand/mt19937/mt19937.v index 256fc069c8..bcb6d8f259 100644 --- a/vlib/rand/mt19937/mt19937.v +++ b/vlib/rand/mt19937/mt19937.v @@ -323,3 +323,9 @@ pub fn (mut rng MT19937RNG) f64_in_range(min f64, max f64) f64 { } return min + rng.f64n(max - min) } + +// free should be called when the generator is no longer needed +[unsafe] +pub fn (mut rng MT19937RNG) free() { + unsafe { free(rng) } +} diff --git a/vlib/rand/musl/musl_rng.v b/vlib/rand/musl/musl_rng.v index fdfb733fc3..2e484d22ab 100644 --- a/vlib/rand/musl/musl_rng.v +++ b/vlib/rand/musl/musl_rng.v @@ -239,3 +239,9 @@ pub fn (mut rng MuslRNG) f64_in_range(min f64, max f64) f64 { } return min + rng.f64n(max - min) } + +// free should be called when the generator is no longer needed +[unsafe] +pub fn (mut rng MuslRNG) free() { + unsafe { free(rng) } +} diff --git a/vlib/rand/pcg32/pcg32.v b/vlib/rand/pcg32/pcg32.v index ba77a3d91e..91577e98a2 100644 --- a/vlib/rand/pcg32/pcg32.v +++ b/vlib/rand/pcg32/pcg32.v @@ -224,3 +224,9 @@ pub fn (mut rng PCG32RNG) f64_in_range(min f64, max f64) f64 { } return min + rng.f64n(max - min) } + +// free should be called when the generator is no longer needed +[unsafe] +pub fn (mut rng PCG32RNG) free() { + unsafe { free(rng) } +} diff --git a/vlib/rand/rand.v b/vlib/rand/rand.v index d790dd5824..29b813649e 100644 --- a/vlib/rand/rand.v +++ b/vlib/rand/rand.v @@ -31,6 +31,7 @@ pub interface PRNG { f64n(max f64) f64 f32_in_range(min f32, max f32) f32 f64_in_range(min f64, max f64) f64 + free() } __global ( @@ -40,13 +41,23 @@ __global ( // init initializes the default RNG. fn init() { default_rng = new_default() + C.atexit(deinit) +} + +fn deinit() { + unsafe { + default_rng.free() // free the implementation + free(default_rng) // free the interface wrapper itself + } } // new_default returns a new instance of the default RNG. If the seed is not provided, the current time will be used to seed the instance. +[manualfree] pub fn new_default(config config.PRNGConfigStruct) &PRNG { mut rng := &wyrand.WyRandRNG{} rng.seed(config.seed_) - return rng + unsafe { config.seed_.free() } + return &PRNG(rng) } // get_current_rng returns the PRNG instance currently in use. If it is not changed, it will be an instance of wyrand.WyRandRNG. diff --git a/vlib/rand/seed/seed.v b/vlib/rand/seed/seed.v index 3b1ef7a607..16de517095 100644 --- a/vlib/rand/seed/seed.v +++ b/vlib/rand/seed/seed.v @@ -12,7 +12,6 @@ fn nr_next(prev u32) u32 { } // time_seed_array returns the required number of u32s generated from system time. -[inline] pub fn time_seed_array(count int) []u32 { ctime := time.sys_mono_now() mut seed := u32(ctime >> 32 ^ (ctime & 0x0000_0000_FFFF_FFFF)) @@ -25,16 +24,21 @@ pub fn time_seed_array(count int) []u32 { } // time_seed_32 returns a 32-bit seed generated from system time. -[inline] +[manualfree] pub fn time_seed_32() u32 { - return time_seed_array(1)[0] + sa := time_seed_array(1) + res := sa[0] + unsafe { sa.free() } + return res } // time_seed_64 returns a 64-bit seed generated from system time. -[inline] +[manualfree] pub fn time_seed_64() u64 { seed_data := time_seed_array(2) lower := u64(seed_data[0]) upper := u64(seed_data[1]) - return lower | (upper << 32) + unsafe { seed_data.free() } + res := lower | (upper << 32) + return res } diff --git a/vlib/rand/splitmix64/splitmix64.v b/vlib/rand/splitmix64/splitmix64.v index d3cb9d1724..663b9380bc 100644 --- a/vlib/rand/splitmix64/splitmix64.v +++ b/vlib/rand/splitmix64/splitmix64.v @@ -223,3 +223,9 @@ pub fn (mut rng SplitMix64RNG) f64_in_range(min f64, max f64) f64 { } return min + rng.f64n(max - min) } + +// free should be called when the generator is no longer needed +[unsafe] +pub fn (mut rng SplitMix64RNG) free() { + unsafe { free(rng) } +} diff --git a/vlib/rand/sys/system_rng.c.v b/vlib/rand/sys/system_rng.c.v index f1c701deb3..e36527f49e 100644 --- a/vlib/rand/sys/system_rng.c.v +++ b/vlib/rand/sys/system_rng.c.v @@ -273,3 +273,9 @@ pub fn (r SysRNG) f64_in_range(min f64, max f64) f64 { } return min + r.f64n(max - min) } + +// free should be called when the generator is no longer needed +[unsafe] +pub fn (mut rng SysRNG) free() { + unsafe { free(rng) } +} diff --git a/vlib/rand/wyrand/wyrand.v b/vlib/rand/wyrand/wyrand.v index 22b71afbad..23cf2a8ec7 100644 --- a/vlib/rand/wyrand/wyrand.v +++ b/vlib/rand/wyrand/wyrand.v @@ -22,6 +22,12 @@ mut: extra u32 } +// free should be called when the generator is no longer needed +[unsafe] +pub fn (mut rng WyRandRNG) free() { + unsafe { free(rng) } +} + // seed sets the seed, needs only two `u32`s in little-endian format as [lower, higher]. pub fn (mut rng WyRandRNG) seed(seed_data []u32) { if seed_data.len != 2 { diff --git a/vlib/v/tests/valgrind/rand_module.v b/vlib/v/tests/valgrind/rand_module.v new file mode 100644 index 0000000000..e481477ac0 --- /dev/null +++ b/vlib/v/tests/valgrind/rand_module.v @@ -0,0 +1,6 @@ +import rand + +fn main() { + n := rand.intn(1000) + println(n) +}