Skip to content

Commit bc7a2d7

Browse files
committed
rand: bubble up IO messages futher.
The various ...Rng::new() methods can hit IO errors from the OSRng they use, and it seems sensible to expose them at a higher level. Unfortunately, writing e.g. `StdRng::new().unwrap()` gives a much poorer error message than if it failed internally, but this is a problem with all `IoResult`s.
1 parent 0e8c949 commit bc7a2d7

File tree

14 files changed

+102
-77
lines changed

14 files changed

+102
-77
lines changed

src/libcollections/deque.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub mod bench {
5252
map: &mut M,
5353
bh: &mut BenchHarness) {
5454
// setup
55-
let mut rng = rand::XorShiftRng::new();
55+
let mut rng = rand::weak_rng();
5656

5757
map.clear();
5858
for _ in range(0, n) {
@@ -89,7 +89,7 @@ pub mod bench {
8989
map: &mut M,
9090
bh: &mut BenchHarness) {
9191
// setup
92-
let mut rng = rand::XorShiftRng::new();
92+
let mut rng = rand::weak_rng();
9393
let mut keys = slice::from_fn(n, |_| rng.gen::<uint>() % n);
9494

9595
for k in keys.iter() {

src/libgreen/sched.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,12 @@ impl ClosureConverter for UnsafeTaskReceiver {
966966
// worry there.
967967
#[cfg(windows)]
968968
fn new_sched_rng() -> XorShiftRng {
969-
XorShiftRng::new()
969+
match XorShiftRng::new() {
970+
Ok(r) => r,
971+
Err(e) => {
972+
rtabort!("sched: failed to create seeded RNG: {}", e)
973+
}
974+
}
970975
}
971976
#[cfg(unix)]
972977
fn new_sched_rng() -> XorShiftRng {

src/librand/distributions/exponential.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ mod bench {
126126

127127
#[bench]
128128
fn rand_exp(bh: &mut BenchHarness) {
129-
let mut rng = XorShiftRng::new();
129+
let mut rng = XorShiftRng::new().unwrap();
130130
let mut exp = Exp::new(2.71828 * 3.14159);
131131

132132
bh.iter(|| {

src/librand/distributions/gamma.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,14 @@ mod bench {
370370
use self::test::BenchHarness;
371371
use std::mem::size_of;
372372
use distributions::IndependentSample;
373-
use {StdRng, RAND_BENCH_N};
373+
use {XorShiftRng, RAND_BENCH_N};
374374
use super::Gamma;
375375

376376

377377
#[bench]
378378
fn bench_gamma_large_shape(bh: &mut BenchHarness) {
379379
let gamma = Gamma::new(10., 1.0);
380-
let mut rng = StdRng::new();
380+
let mut rng = XorShiftRng::new().unwrap();
381381

382382
bh.iter(|| {
383383
for _ in range(0, RAND_BENCH_N) {
@@ -390,7 +390,7 @@ mod bench {
390390
#[bench]
391391
fn bench_gamma_small_shape(bh: &mut BenchHarness) {
392392
let gamma = Gamma::new(0.1, 1.0);
393-
let mut rng = StdRng::new();
393+
let mut rng = XorShiftRng::new().unwrap();
394394

395395
bh.iter(|| {
396396
for _ in range(0, RAND_BENCH_N) {

src/librand/distributions/normal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ mod bench {
193193

194194
#[bench]
195195
fn rand_normal(bh: &mut BenchHarness) {
196-
let mut rng = XorShiftRng::new();
196+
let mut rng = XorShiftRng::new().unwrap();
197197
let mut normal = Normal::new(-2.71828, 3.14159);
198198

199199
bh.iter(|| {

src/librand/isaac.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//! The ISAAC random number generator.
1212
1313
use {Rng, SeedableRng, OSRng};
14+
use std::io::IoResult;
1415
use std::iter::{range_step, Repeat};
1516
use std::slice::raw;
1617
use std::mem;
@@ -44,12 +45,13 @@ static EMPTY: IsaacRng = IsaacRng {
4445

4546
impl IsaacRng {
4647
/// Create an ISAAC random number generator with a random seed.
47-
pub fn new() -> IsaacRng {
48+
///
49+
/// This reads randomness from the operating system (via `OSRng`)
50+
/// which may fail, any error is propagated via the `IoResult`
51+
/// return value.
52+
pub fn new() -> IoResult<IsaacRng> {
4853
let mut rng = EMPTY;
49-
let mut os_rng = match OSRng::new() {
50-
Ok(r) => r,
51-
Err(e) => fail!("IsaacRng::new: creating OSRng failed: {}", e)
52-
};
54+
let mut os_rng = try!(OSRng::new());
5355
unsafe {
5456
let ptr = rng.rsl.as_mut_ptr();
5557

@@ -59,7 +61,7 @@ impl IsaacRng {
5961
}
6062

6163
rng.init(true);
62-
rng
64+
Ok(rng)
6365
}
6466

6567
/// Create an ISAAC random number generator using the default
@@ -252,12 +254,14 @@ static EMPTY_64: Isaac64Rng = Isaac64Rng {
252254
impl Isaac64Rng {
253255
/// Create a 64-bit ISAAC random number generator with a random
254256
/// seed.
255-
pub fn new() -> Isaac64Rng {
257+
///
258+
/// This reads randomness from the operating system (via `OSRng`)
259+
/// which may fail, any error is propagated via the `IoResult`
260+
/// return value.
261+
pub fn new() -> IoResult<Isaac64Rng> {
256262
let mut rng = EMPTY_64;
257-
let mut os_rng = match OSRng::new() {
258-
Ok(r) => r,
259-
Err(e) => fail!("Isaac64Rng::new: creating OSRng failed: {}", e)
260-
};
263+
let mut os_rng = try!(OSRng::new());
264+
261265
unsafe {
262266
let ptr = rng.rsl.as_mut_ptr();
263267

@@ -267,7 +271,7 @@ impl Isaac64Rng {
267271
}
268272

269273
rng.init(true);
270-
rng
274+
Ok(rng)
271275
}
272276

273277
/// Create a 64-bit ISAAC random number generator using the
@@ -436,19 +440,19 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
436440
#[cfg(test)]
437441
mod test {
438442
use super::{IsaacRng, Isaac64Rng};
439-
use {Rng, SeedableRng, OSRng};
443+
use {Rng, SeedableRng, task_rng};
440444
use std::slice;
441445

442446
#[test]
443447
fn test_rng_32_rand_seeded() {
444-
let s = OSRng::new().gen_vec::<u32>(256);
448+
let s = task_rng().gen_vec::<u32>(256);
445449
let mut ra: IsaacRng = SeedableRng::from_seed(s.as_slice());
446450
let mut rb: IsaacRng = SeedableRng::from_seed(s.as_slice());
447451
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
448452
}
449453
#[test]
450454
fn test_rng_64_rand_seeded() {
451-
let s = OSRng::new().gen_vec::<u64>(256);
455+
let s = task_rng().gen_vec::<u64>(256);
452456
let mut ra: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
453457
let mut rb: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
454458
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
@@ -471,7 +475,7 @@ mod test {
471475

472476
#[test]
473477
fn test_rng_32_reseed() {
474-
let s = OSRng::new().gen_vec::<u32>(256);
478+
let s = task_rng().gen_vec::<u32>(256);
475479
let mut r: IsaacRng = SeedableRng::from_seed(s.as_slice());
476480
let string1 = r.gen_ascii_str(100);
477481

@@ -482,7 +486,7 @@ mod test {
482486
}
483487
#[test]
484488
fn test_rng_64_reseed() {
485-
let s = OSRng::new().gen_vec::<u64>(256);
489+
let s = task_rng().gen_vec::<u64>(256);
486490
let mut r: Isaac64Rng = SeedableRng::from_seed(s.as_slice());
487491
let string1 = r.gen_ascii_str(100);
488492

src/librand/lib.rs

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ println!("{:?}", tuple_ptr)
7676
#[phase(syntax, link)] extern crate log;
7777

7878
use std::cast;
79+
use std::io::IoResult;
7980
use std::kinds::marker;
8081
use std::local_data;
8182
use std::str;
@@ -401,7 +402,7 @@ pub trait SeedableRng<Seed>: Rng {
401402
/// appropriate.
402403
#[deprecated="use `task_rng` or `StdRng::new`"]
403404
pub fn rng() -> StdRng {
404-
StdRng::new()
405+
StdRng::new().unwrap()
405406
}
406407

407408
/// The standard RNG. This is designed to be efficient on the current
@@ -423,9 +424,12 @@ impl StdRng {
423424
/// number of random numbers, or doesn't need the utmost speed for
424425
/// generating each number, `task_rng` and/or `random` may be more
425426
/// appropriate.
427+
///
428+
/// Reading the randomness from the OS may fail, and any error is
429+
/// propagated via the `IoResult` return value.
426430
#[cfg(not(target_word_size="64"))]
427-
pub fn new() -> StdRng {
428-
StdRng { rng: IsaacRng::new() }
431+
pub fn new() -> IoResult<StdRng> {
432+
IsaacRng::new().map(|r| StdRng { rng: r })
429433
}
430434
/// Create a randomly seeded instance of `StdRng`.
431435
///
@@ -435,9 +439,12 @@ impl StdRng {
435439
/// number of random numbers, or doesn't need the utmost speed for
436440
/// generating each number, `task_rng` and/or `random` may be more
437441
/// appropriate.
442+
///
443+
/// Reading the randomness from the OS may fail, and any error is
444+
/// propagated via the `IoResult` return value.
438445
#[cfg(target_word_size="64")]
439-
pub fn new() -> StdRng {
440-
StdRng { rng: Isaac64Rng::new() }
446+
pub fn new() -> IoResult<StdRng> {
447+
Isaac64Rng::new().map(|r| StdRng { rng: r })
441448
}
442449
}
443450

@@ -475,7 +482,10 @@ impl<'a> SeedableRng<&'a [uint]> for StdRng {
475482
/// This will read randomness from the operating system to seed the
476483
/// generator.
477484
pub fn weak_rng() -> XorShiftRng {
478-
XorShiftRng::new()
485+
match XorShiftRng::new() {
486+
Ok(r) => r,
487+
Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
488+
}
479489
}
480490

481491
/// An Xorshift[1] random number
@@ -537,21 +547,18 @@ impl SeedableRng<[u32, .. 4]> for XorShiftRng {
537547

538548
impl XorShiftRng {
539549
/// Create an xor shift random number generator with a random seed.
540-
pub fn new() -> XorShiftRng {
550+
pub fn new() -> IoResult<XorShiftRng> {
541551
let mut s = [0u8, ..16];
552+
let mut r = try!(OSRng::new());
542553
loop {
543-
let mut r = match OSRng::new() {
544-
Ok(r) => r,
545-
Err(e) => fail!("XorShiftRng::new: creating OSRng failed: {}", e)
546-
};
547554
r.fill_bytes(s);
548555

549556
if !s.iter().all(|x| *x == 0) {
550557
break;
551558
}
552559
}
553560
let s: [u32, ..4] = unsafe { cast::transmute(s) };
554-
SeedableRng::from_seed(s)
561+
Ok(SeedableRng::from_seed(s))
555562
}
556563
}
557564

@@ -560,7 +567,10 @@ struct TaskRngReseeder;
560567

561568
impl reseeding::Reseeder<StdRng> for TaskRngReseeder {
562569
fn reseed(&mut self, rng: &mut StdRng) {
563-
*rng = StdRng::new();
570+
*rng = match StdRng::new() {
571+
Ok(r) => r,
572+
Err(e) => fail!("could not reseed task_rng: {}", e)
573+
}
564574
}
565575
}
566576
static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
@@ -597,7 +607,11 @@ local_data_key!(TASK_RNG_KEY: ~TaskRngInner)
597607
pub fn task_rng() -> TaskRng {
598608
local_data::get_mut(TASK_RNG_KEY, |rng| match rng {
599609
None => {
600-
let mut rng = ~reseeding::ReseedingRng::new(StdRng::new(),
610+
let r = match StdRng::new() {
611+
Ok(r) => r,
612+
Err(e) => fail!("could not initialize task_rng: {}", e)
613+
};
614+
let mut rng = ~reseeding::ReseedingRng::new(r,
601615
TASK_RNG_RESEED_THRESHOLD,
602616
TaskRngReseeder);
603617
let ptr = &mut *rng as *mut TaskRngInner;
@@ -680,7 +694,7 @@ pub struct Closed01<F>(F);
680694
#[cfg(test)]
681695
mod test {
682696
use std::slice;
683-
use super::{Rng, task_rng, random, OSRng, SeedableRng, StdRng};
697+
use super::{Rng, task_rng, random, SeedableRng, StdRng};
684698

685699
struct ConstRng { i: u64 }
686700
impl Rng for ConstRng {
@@ -842,15 +856,15 @@ mod test {
842856

843857
#[test]
844858
fn test_std_rng_seeded() {
845-
let s = OSRng::new().gen_vec::<uint>(256);
859+
let s = task_rng().gen_vec::<uint>(256);
846860
let mut ra: StdRng = SeedableRng::from_seed(s.as_slice());
847861
let mut rb: StdRng = SeedableRng::from_seed(s.as_slice());
848862
assert_eq!(ra.gen_ascii_str(100u), rb.gen_ascii_str(100u));
849863
}
850864

851865
#[test]
852866
fn test_std_rng_reseed() {
853-
let s = OSRng::new().gen_vec::<uint>(256);
867+
let s = task_rng().gen_vec::<uint>(256);
854868
let mut r: StdRng = SeedableRng::from_seed(s.as_slice());
855869
let string1 = r.gen_ascii_str(100);
856870

@@ -873,7 +887,7 @@ mod bench {
873887

874888
#[bench]
875889
fn rand_xorshift(bh: &mut BenchHarness) {
876-
let mut rng = XorShiftRng::new();
890+
let mut rng = XorShiftRng::new().unwrap();
877891
bh.iter(|| {
878892
for _ in range(0, RAND_BENCH_N) {
879893
rng.gen::<uint>();
@@ -884,7 +898,7 @@ mod bench {
884898

885899
#[bench]
886900
fn rand_isaac(bh: &mut BenchHarness) {
887-
let mut rng = IsaacRng::new();
901+
let mut rng = IsaacRng::new().unwrap();
888902
bh.iter(|| {
889903
for _ in range(0, RAND_BENCH_N) {
890904
rng.gen::<uint>();
@@ -895,7 +909,7 @@ mod bench {
895909

896910
#[bench]
897911
fn rand_isaac64(bh: &mut BenchHarness) {
898-
let mut rng = Isaac64Rng::new();
912+
let mut rng = Isaac64Rng::new().unwrap();
899913
bh.iter(|| {
900914
for _ in range(0, RAND_BENCH_N) {
901915
rng.gen::<uint>();
@@ -906,7 +920,7 @@ mod bench {
906920

907921
#[bench]
908922
fn rand_std(bh: &mut BenchHarness) {
909-
let mut rng = StdRng::new();
923+
let mut rng = StdRng::new().unwrap();
910924
bh.iter(|| {
911925
for _ in range(0, RAND_BENCH_N) {
912926
rng.gen::<uint>();
@@ -917,7 +931,7 @@ mod bench {
917931

918932
#[bench]
919933
fn rand_shuffle_100(bh: &mut BenchHarness) {
920-
let mut rng = XorShiftRng::new();
934+
let mut rng = XorShiftRng::new().unwrap();
921935
let x : &mut[uint] = [1,..100];
922936
bh.iter(|| {
923937
rng.shuffle_mut(x);

src/librand/os.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ mod test {
192192

193193
#[test]
194194
fn test_os_rng() {
195-
let mut r = OSRng::new();
195+
let mut r = OSRng::new().unwrap();
196196

197197
r.next_u32();
198198
r.next_u64();
@@ -214,7 +214,7 @@ mod test {
214214

215215
// deschedule to attempt to interleave things as much
216216
// as possible (XXX: is this a good test?)
217-
let mut r = OSRng::new();
217+
let mut r = OSRng::new().unwrap();
218218
task::deschedule();
219219
let mut v = [0u8, .. 1000];
220220

0 commit comments

Comments
 (0)