fn test_rand_sample() {
let mut rand_sample = RandSample::<ConstRand>;
- assert_eq!(*rand_sample.sample(task_rng()), 0);
- assert_eq!(*rand_sample.ind_sample(task_rng()), 0);
+ assert_eq!(*rand_sample.sample(&mut task_rng()), 0);
+ assert_eq!(*rand_sample.ind_sample(&mut task_rng()), 0);
}
#[test]
fn test_normal() {
let mut norm = Normal::new(10.0, 10.0);
- let rng = task_rng();
+ let mut rng = task_rng();
for _ in range(0, 1000) {
- norm.sample(rng);
- norm.ind_sample(rng);
+ norm.sample(&mut rng);
+ norm.ind_sample(&mut rng);
}
}
#[test]
#[test]
fn test_exp() {
let mut exp = Exp::new(10.0);
- let rng = task_rng();
+ let mut rng = task_rng();
for _ in range(0, 1000) {
- assert!(exp.sample(rng) >= 0.0);
- assert!(exp.ind_sample(rng) >= 0.0);
+ assert!(exp.sample(&mut rng) >= 0.0);
+ assert!(exp.ind_sample(&mut rng) >= 0.0);
}
}
#[test]
#[test]
fn test_integers() {
- let rng = task_rng();
+ let mut rng = task_rng();
macro_rules! t (
($($ty:ty),*) => {{
$(
for &(low, high) in v.iter() {
let mut sampler: Range<$ty> = Range::new(low, high);
for _ in range(0, 1000) {
- let v = sampler.sample(rng);
+ let v = sampler.sample(&mut rng);
assert!(low <= v && v < high);
- let v = sampler.ind_sample(rng);
+ let v = sampler.ind_sample(&mut rng);
assert!(low <= v && v < high);
}
}
#[test]
fn test_floats() {
- let rng = task_rng();
+ let mut rng = task_rng();
macro_rules! t (
($($ty:ty),*) => {{
$(
for &(low, high) in v.iter() {
let mut sampler: Range<$ty> = Range::new(low, high);
for _ in range(0, 1000) {
- let v = sampler.sample(rng);
+ let v = sampler.sample(&mut rng);
assert!(low <= v && v < high);
- let v = sampler.ind_sample(rng);
+ let v = sampler.ind_sample(&mut rng);
assert!(low <= v && v < high);
}
}
}
}
static TASK_RNG_RESEED_THRESHOLD: uint = 32_768;
+type TaskRngInner = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
/// The task-local RNG.
-pub type TaskRng = reseeding::ReseedingRng<StdRng, TaskRngReseeder>;
+#[no_send]
+pub struct TaskRng {
+ // This points into TLS (specifically, it points to the endpoint
+ // of a ~ stored in TLS, to make it robust against TLS moving
+ // things internally) and so this struct cannot be legally
+ // transferred between tasks *and* it's unsafe to deallocate the
+ // RNG other than when a task is finished.
+ //
+ // The use of unsafe code here is OK if the invariants above are
+ // satisfied; and it allows us to avoid (unnecessarily) using a
+ // GC'd or RC'd pointer.
+ priv rng: *mut TaskRngInner
+}
// used to make space in TLS for a random number generator
-local_data_key!(TASK_RNG_KEY: @mut TaskRng)
+local_data_key!(TASK_RNG_KEY: ~TaskRngInner)
/// Retrieve the lazily-initialized task-local random number
/// generator, seeded by the system. Intended to be used in method
/// if the operating system random number generator is rigged to give
/// the same sequence always. If absolute consistency is required,
/// explicitly select an RNG, e.g. `IsaacRng` or `Isaac64Rng`.
-pub fn task_rng() -> @mut TaskRng {
- let r = local_data::get(TASK_RNG_KEY, |k| k.map(|k| *k));
- match r {
+pub fn task_rng() -> TaskRng {
+ local_data::get_mut(TASK_RNG_KEY, |rng| match rng {
None => {
- let rng = @mut reseeding::ReseedingRng::new(StdRng::new(),
+ let mut rng = ~reseeding::ReseedingRng::new(StdRng::new(),
TASK_RNG_RESEED_THRESHOLD,
TaskRngReseeder);
+ let ptr = &mut *rng as *mut TaskRngInner;
+
local_data::set(TASK_RNG_KEY, rng);
- rng
+
+ TaskRng { rng: ptr }
}
- Some(rng) => rng
- }
+ Some(rng) => TaskRng { rng: &mut **rng }
+ })
}
-// Allow direct chaining with `task_rng`
-impl<R: Rng> Rng for @mut R {
- #[inline]
+impl Rng for TaskRng {
fn next_u32(&mut self) -> u32 {
- (**self).next_u32()
+ unsafe { (*self.rng).next_u32() }
}
- #[inline]
+
fn next_u64(&mut self) -> u64 {
- (**self).next_u64()
+ unsafe { (*self.rng).next_u64() }
}
#[inline]
fn fill_bytes(&mut self, bytes: &mut [u8]) {
- (**self).fill_bytes(bytes);
+ unsafe { (*self.rng).fill_bytes(bytes) }
}
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ensure that the TaskRng isn't/doesn't become accidentally sendable.
+
+fn test_send<S: Send>() {}
+
+pub fn main() {
+ test_send::<::std::rand::TaskRng>();
+ //~^ ERROR: incompatible type `std::rand::TaskRng`, which does not fulfill `Send`
+}