Skip to content

Commit adc05ed

Browse files
committed
---
yaml --- r: 95281 b: refs/heads/dist-snap c: fb97063 h: refs/heads/master i: 95279: 724c9cc v: v3
1 parent 087027e commit adc05ed

File tree

3 files changed

+135
-21
lines changed

3 files changed

+135
-21
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ refs/heads/try: c274a6888410ce3e357e014568b43310ed787d36
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: 147ecfdd8221e4a4d4e090486829a06da1e0ca3c
9-
refs/heads/dist-snap: 92725ae765a75b139d5d5fc27305f4436dbb456e
9+
refs/heads/dist-snap: fb9706338d56599ea3073b5f8e93c2e769431a48
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503
1212
refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0

branches/dist-snap/src/libstd/rand/mod.rs

Lines changed: 116 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use u32;
5454
use u64;
5555
use uint;
5656
use vec;
57+
use os::getenv;
5758

5859
pub use self::isaac::{IsaacRng, Isaac64Rng};
5960
pub use self::os::OSRng;
@@ -284,15 +285,15 @@ pub trait Rng {
284285
///
285286
/// # Example
286287
///
287-
/// ~~~{.rust}
288+
/// ```rust
288289
/// use std::rand::{task_rng, Rng};
289290
///
290291
/// fn main() {
291292
/// let mut v = [0u8, .. 13579];
292293
/// task_rng().fill_bytes(v);
293294
/// printfln!(v);
294295
/// }
295-
/// ~~~
296+
/// ```
296297
fn fill_bytes(&mut self, mut dest: &mut [u8]) {
297298
// this relies on the lengths being transferred correctly when
298299
// transmuting between vectors like this.
@@ -700,12 +701,16 @@ pub struct StdRng { priv rng: IsaacRng }
700701
pub struct StdRng { priv rng: Isaac64Rng }
701702

702703
impl StdRng {
704+
/// Create a randomly seeded instance of `StdRng`. This reads
705+
/// randomness from the OS to seed the PRNG.
703706
#[cfg(not(target_word_size="64"))]
704-
fn new() -> StdRng {
707+
pub fn new() -> StdRng {
705708
StdRng { rng: IsaacRng::new() }
706709
}
710+
/// Create a randomly seeded instance of `StdRng`. This reads
711+
/// randomness from the OS to seed the PRNG.
707712
#[cfg(target_word_size="64")]
708-
fn new() -> StdRng {
713+
pub fn new() -> StdRng {
709714
StdRng { rng: Isaac64Rng::new() }
710715
}
711716
}
@@ -830,27 +835,96 @@ pub unsafe fn seed<T: Clone>(n: uint) -> ~[T] {
830835
s
831836
}
832837

838+
/// Controls how the task-local RNG is reseeded.
839+
enum TaskRngReseeder {
840+
/// Reseed using the StdRng::new() function, i.e. reading new
841+
/// randomness.
842+
WithNew,
843+
/// Don't reseed at all, e.g. when it has been explicitly seeded
844+
/// by the user.
845+
DontReseed
846+
}
847+
848+
impl Default for TaskRngReseeder {
849+
fn default() -> TaskRngReseeder { WithNew }
850+
}
851+
852+
impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
853+
fn reseed(&mut self, rng: &mut StdRng) {
854+
match *self {
855+
WithNew => *rng = StdRng::new(),
856+
DontReseed => {}
857+
}
858+
}
859+
}
860+
static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
861+
/// The task-local RNG.
862+
pub type TaskRng = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
863+
833864
// used to make space in TLS for a random number generator
834-
local_data_key!(tls_rng_state: @mut StdRng)
865+
local_data_key!(TASK_RNG_KEY: @mut TaskRng)
835866

836-
/**
837-
* Gives back a lazily initialized task-local random number generator,
838-
* seeded by the system. Intended to be used in method chaining style, ie
839-
* `task_rng().gen::<int>()`.
840-
*/
841-
#[inline]
842-
pub fn task_rng() -> @mut StdRng {
843-
let r = local_data::get(tls_rng_state, |k| k.map(|&k| *k));
867+
/// Retrieve the lazily-initialized task-local random number
868+
/// generator, seeded by the system. Intended to be used in method
869+
/// chaining style, e.g. `task_rng().gen::<int>()`.
870+
///
871+
/// The RNG provided will reseed itself from the operating system
872+
/// after generating a certain amount of randomness, unless it was
873+
/// explicitly seeded either by `seed_task_rng` or by setting the
874+
/// `RUST_SEED` environmental variable to some integer.
875+
///
876+
/// The internal RNG used is platform and architecture dependent, so
877+
/// may yield differing sequences on different computers, even when
878+
/// explicitly seeded with `seed_task_rng`. If absolute consistency is
879+
/// required, explicitly select an RNG, e.g. `IsaacRng` or
880+
/// `Isaac64Rng`.
881+
pub fn task_rng() -> @mut TaskRng {
882+
let r = local_data::get(TASK_RNG_KEY, |k| k.map(|&k| *k));
844883
match r {
845884
None => {
846-
let rng = @mut StdRng::new();
847-
local_data::set(tls_rng_state, rng);
885+
// check the environment
886+
let (sub_rng, reseeder) = match getenv("RUST_SEED") {
887+
None => (StdRng::new(), WithNew),
888+
889+
Some(s) => match from_str::<uint>(s) {
890+
None => fail2!("`RUST_SEED` is `{}`, should be a positive integer.", s),
891+
// explicitly seeded, so don't overwrite the seed later.
892+
Some(seed) => (SeedableRng::from_seed(&[seed]), DontReseed),
893+
}
894+
};
895+
896+
let rng = @mut reseeding::ReseedingRng::new(sub_rng,
897+
TASK_RNG_RESEED_THRESHOLD,
898+
reseeder);
899+
local_data::set(TASK_RNG_KEY, rng);
848900
rng
849901
}
850902
Some(rng) => rng
851903
}
852904
}
853905

906+
/// Explicitly seed (or reseed) the task-local random number
907+
/// generator. This stops the RNG from automatically reseeding itself.
908+
///
909+
/// # Example
910+
///
911+
/// ```rust
912+
/// use std::rand;
913+
///
914+
/// fn main() {
915+
/// rand::seed_task_rng(&[10u]);
916+
/// printfln!("Same every time: %u", rand::random::<uint>());
917+
///
918+
/// rand::seed_task_rng(&[1u, 2, 3, 4, 5, 6, 7, 8]);
919+
/// printfln!("Same every time: %f", rand::random::<float>());
920+
/// }
921+
/// ```
922+
pub fn seed_task_rng(seed: &[uint]) {
923+
let t_r = task_rng();
924+
(*t_r).reseed(seed);
925+
t_r.reseeder = DontReseed;
926+
}
927+
854928
// Allow direct chaining with `task_rng`
855929
impl<R: Rng> Rng for @mut R {
856930
#[inline]
@@ -863,10 +937,23 @@ impl<R: Rng> Rng for @mut R {
863937
}
864938
}
865939

866-
/**
867-
* Returns a random value of a Rand type, using the task's random number
868-
* generator.
869-
*/
940+
/// Generate a random value using the task-local random number
941+
/// generator.
942+
///
943+
/// # Example
944+
///
945+
/// ```rust
946+
/// use std::rand::random;
947+
///
948+
/// fn main() {
949+
/// if random() {
950+
/// let x = random();
951+
/// printfln!(2u * x);
952+
/// } else {
953+
/// printfln!(random::<float>());
954+
/// }
955+
/// }
956+
/// ```
870957
#[inline]
871958
pub fn random<T: Rand>() -> T {
872959
task_rng().gen()
@@ -1053,6 +1140,16 @@ mod test {
10531140
**e >= MIN_VAL && **e <= MAX_VAL
10541141
}));
10551142
}
1143+
1144+
#[test]
1145+
fn test_seed_task_rng() {
1146+
seed_task_rng([1]);
1147+
let first = random::<uint>();
1148+
1149+
seed_task_rng([1]);
1150+
let second = random::<uint>();
1151+
assert_eq!(first, second);
1152+
}
10561153
}
10571154

10581155
#[cfg(test)]

branches/dist-snap/src/libstd/rand/reseeding.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//! A wrapper around another RNG that reseeds it after it
1212
//! generates a certain number of random bytes.
1313
14-
use rand::Rng;
14+
use rand::{Rng, SeedableRng};
1515
use default::Default;
1616

1717
/// How many bytes of entropy the underling RNG is allowed to generate
@@ -76,6 +76,23 @@ impl<R: Rng, Rsdr: Reseeder<R>> Rng for ReseedingRng<R, Rsdr> {
7676
}
7777
}
7878

79+
impl<S, R: SeedableRng<S>, Rsdr: Reseeder<R> + Default> SeedableRng<S> for ReseedingRng<R, Rsdr> {
80+
fn reseed(&mut self, seed: S) {
81+
self.rng.reseed(seed);
82+
self.bytes_generated = 0;
83+
}
84+
/// Create a new `ReseedingRng` from the given seed. This uses
85+
/// default values for both `generation_threshold` and `reseeder`.
86+
fn from_seed(seed: S) -> ReseedingRng<R, Rsdr> {
87+
ReseedingRng {
88+
rng: SeedableRng::from_seed(seed),
89+
generation_threshold: DEFAULT_GENERATION_THRESHOLD,
90+
bytes_generated: 0,
91+
reseeder: Default::default()
92+
}
93+
}
94+
}
95+
7996
/// Something that can be used to reseed an RNG via `ReseedingRng`.
8097
pub trait Reseeder<R> {
8198
/// Reseed the given RNG.

0 commit comments

Comments
 (0)