// 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 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering}; use std::rand::{thread_rng, Rng, Rand}; use std::thread::Thread; const REPEATS: uint = 5; const MAX_LEN: uint = 32; static drop_counts: [AtomicUint; MAX_LEN] = // FIXME #5244: AtomicUint is not Copy. [ 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_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_INIT, ]; static creation_count: AtomicUint = ATOMIC_UINT_INIT; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] struct DropCounter { x: uint, creation_id: uint } impl Rand for DropCounter { fn rand(rng: &mut R) -> DropCounter { // (we're not using this concurrently, so Relaxed is fine.) let num = creation_count.fetch_add(1, Ordering::Relaxed); DropCounter { x: rng.gen(), creation_id: num } } } impl Drop for DropCounter { fn drop(&mut self) { drop_counts[self.creation_id].fetch_add(1, Ordering::Relaxed); } } pub fn main() { assert!(MAX_LEN <= std::uint::BITS); // len can't go above 64. 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, Ordering::Relaxed); let main = thread_rng().gen_iter::() .take(len) .collect::>(); // work out the total number of comparisons required to sort // this array... let mut count = 0; main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) }); // ... and then panic on each and every single one. for panic_countdown in range(0i, count) { // refresh the counters. for c in drop_counts.iter() { c.store(0, Ordering::Relaxed); } let v = main.clone(); let _ = Thread::scoped(move|| { let mut v = v; let mut panic_countdown = panic_countdown; v.as_mut_slice().sort_by(|a, b| { if panic_countdown == 0 { panic!() } panic_countdown -= 1; a.cmp(b) }) }).join(); // check that the number of things dropped is exactly // what we expect (i.e. the contents of `v`). for (i, c) in drop_counts.iter().enumerate().take(len) { let count = c.load(Ordering::Relaxed); assert!(count == 1, "found drop count == {} for i == {}, len == {}", count, i, len); } } } } }