]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2013 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
c34b1796 AL |
11 | // pretty-expanded FIXME #23616 |
12 | ||
13 | #![feature(rand, core)] | |
14 | ||
85aaf69f | 15 | use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; |
1a4d82fc | 16 | use std::rand::{thread_rng, Rng, Rand}; |
85aaf69f | 17 | use std::thread; |
1a4d82fc | 18 | |
85aaf69f SL |
19 | const REPEATS: usize = 5; |
20 | const MAX_LEN: usize = 32; | |
21 | static drop_counts: [AtomicUsize; MAX_LEN] = | |
22 | // FIXME #5244: AtomicUsize is not Copy. | |
1a4d82fc | 23 | [ |
85aaf69f SL |
24 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, |
25 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
26 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
27 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
28 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
29 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
30 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
31 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
32 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
33 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
34 | ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, | |
1a4d82fc JJ |
35 | ]; |
36 | ||
85aaf69f | 37 | static creation_count: AtomicUsize = ATOMIC_USIZE_INIT; |
1a4d82fc JJ |
38 | |
39 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)] | |
85aaf69f | 40 | struct DropCounter { x: usize, creation_id: usize } |
1a4d82fc JJ |
41 | |
42 | impl Rand for DropCounter { | |
43 | fn rand<R: Rng>(rng: &mut R) -> DropCounter { | |
44 | // (we're not using this concurrently, so Relaxed is fine.) | |
45 | let num = creation_count.fetch_add(1, Ordering::Relaxed); | |
46 | DropCounter { | |
47 | x: rng.gen(), | |
48 | creation_id: num | |
49 | } | |
50 | } | |
51 | } | |
52 | ||
53 | impl Drop for DropCounter { | |
54 | fn drop(&mut self) { | |
55 | drop_counts[self.creation_id].fetch_add(1, Ordering::Relaxed); | |
56 | } | |
57 | } | |
58 | ||
59 | pub fn main() { | |
c34b1796 | 60 | assert!(MAX_LEN <= std::usize::BITS as usize); |
1a4d82fc | 61 | // len can't go above 64. |
85aaf69f SL |
62 | for len in 2..MAX_LEN { |
63 | for _ in 0..REPEATS { | |
1a4d82fc JJ |
64 | // reset the count for these new DropCounters, so their |
65 | // IDs start from 0. | |
66 | creation_count.store(0, Ordering::Relaxed); | |
67 | ||
68 | let main = thread_rng().gen_iter::<DropCounter>() | |
69 | .take(len) | |
70 | .collect::<Vec<DropCounter>>(); | |
71 | ||
72 | // work out the total number of comparisons required to sort | |
73 | // this array... | |
85aaf69f SL |
74 | let mut count = 0_usize; |
75 | main.clone().sort_by(|a, b| { count += 1; a.cmp(b) }); | |
1a4d82fc JJ |
76 | |
77 | // ... and then panic on each and every single one. | |
85aaf69f | 78 | for panic_countdown in 0..count { |
1a4d82fc | 79 | // refresh the counters. |
85aaf69f | 80 | for c in &drop_counts { |
1a4d82fc JJ |
81 | c.store(0, Ordering::Relaxed); |
82 | } | |
83 | ||
84 | let v = main.clone(); | |
85 | ||
85aaf69f | 86 | let _ = thread::spawn(move|| { |
1a4d82fc JJ |
87 | let mut v = v; |
88 | let mut panic_countdown = panic_countdown; | |
85aaf69f | 89 | v.sort_by(|a, b| { |
1a4d82fc JJ |
90 | if panic_countdown == 0 { |
91 | panic!() | |
92 | } | |
93 | panic_countdown -= 1; | |
94 | a.cmp(b) | |
95 | }) | |
96 | }).join(); | |
97 | ||
98 | // check that the number of things dropped is exactly | |
99 | // what we expect (i.e. the contents of `v`). | |
100 | for (i, c) in drop_counts.iter().enumerate().take(len) { | |
101 | let count = c.load(Ordering::Relaxed); | |
102 | assert!(count == 1, | |
103 | "found drop count == {} for i == {}, len == {}", | |
104 | count, i, len); | |
105 | } | |
106 | } | |
107 | } | |
108 | } | |
109 | } |