// except according to those terms.
use std::task;
-use std::rand::{task_rng, Rng};
+use std::sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};
+use std::rand::{task_rng, Rng, Rand};
-const MAX_LEN: uint = 20;
-static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
-static mut clone_count: uint = 0;
+const REPEATS: uint = 5;
+const MAX_LEN: uint = 32;
+static drop_counts: [AtomicUint, .. MAX_LEN] =
+ // FIXME #5244: AtomicUint is not Copy.
+ [
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
-#[deriving(Rand, PartialEq, PartialOrd, Eq, Ord)]
-struct DropCounter { x: uint, clone_num: uint }
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT, INIT_ATOMIC_UINT,
+ ];
-impl Clone for DropCounter {
- fn clone(&self) -> DropCounter {
- let num = unsafe { clone_count };
- unsafe { clone_count += 1; }
+static creation_count: AtomicUint = INIT_ATOMIC_UINT;
+
+#[deriving(Clone, PartialEq, PartialOrd, Eq, Ord)]
+struct DropCounter { x: uint, creation_id: uint }
+
+impl Rand for DropCounter {
+ fn rand<R: Rng>(rng: &mut R) -> DropCounter {
+ // (we're not using this concurrently, so Relaxed is fine.)
+ let num = creation_count.fetch_add(1, Relaxed);
DropCounter {
- x: self.x,
- clone_num: num
+ x: rng.gen(),
+ creation_id: num
}
}
}
impl Drop for DropCounter {
fn drop(&mut self) {
- unsafe {
- // Rand creates some with arbitrary clone_nums
- if self.clone_num < MAX_LEN {
- drop_counts[self.clone_num] += 1;
- }
- }
+ drop_counts[self.creation_id].fetch_add(1, Relaxed);
}
}
pub fn main() {
+ assert!(MAX_LEN <= std::uint::BITS);
// len can't go above 64.
- for len in range(2u, MAX_LEN) {
- for _ in range(0i, 10) {
+ for len in range(2, MAX_LEN) {
+ for _ in range(0, REPEATS) {
+ // reset the count for these new DropCounters, so their
+ // IDs start from 0.
+ creation_count.store(0, Relaxed);
+
let main = task_rng().gen_iter::<DropCounter>()
.take(len)
.collect::<Vec<DropCounter>>();
// ... and then fail on each and every single one.
for fail_countdown in range(0i, count) {
// refresh the counters.
- unsafe {
- drop_counts = [0, .. MAX_LEN];
- clone_count = 0;
+ for c in drop_counts.iter() {
+ c.store(0, Relaxed);
}
let v = main.clone();
- task::try(proc() {
+ let _ = task::try(proc() {
let mut v = v;
let mut fail_countdown = fail_countdown;
v.as_mut_slice().sort_by(|a, b| {
// check that the number of things dropped is exactly
// what we expect (i.e. the contents of `v`).
- unsafe {
- for (i, &c) in drop_counts.iter().enumerate() {
- let expected = if i < len {1} else {0};
- assert!(c == expected,
- "found drop count == {} for i == {}, len == {}",
- c, i, len);
- }
+ for (i, c) in drop_counts.iter().enumerate().take(len) {
+ let count = c.load(Relaxed);
+ assert!(count == 1,
+ "found drop count == {} for i == {}, len == {}",
+ count, i, len);
}
}
}