1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#[macro_export]
macro_rules! generate_counter {
($name:ident, $type:ident) => {
#[allow(non_snake_case)]
pub mod $name {
use std::cell::Cell;
thread_local!(
static COUNTER: Cell<$type> = Cell::new(0);
);
pub fn next() -> $type {
COUNTER.with(|cell| {
let n = cell.get();
cell.set(n + 1);
n
})
}
#[allow(dead_code)]
pub fn set(n: $type) {
COUNTER.with(|cell| cell.set(n));
}
#[allow(dead_code)]
pub fn reset() {
COUNTER.with(|cell| cell.set(0));
}
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_basic() {
generate_counter!(Counter, i8);
assert_eq!(0, Counter::next());
assert_eq!(1, Counter::next());
assert_eq!(2, Counter::next());
}
#[test]
fn test_reset() {
generate_counter!(Counter, i8);
assert_eq!(0, Counter::next());
assert_eq!(1, Counter::next());
Counter::reset();
assert_eq!(0, Counter::next());
}
#[test]
fn test_set() {
generate_counter!(Counter, u32);
Counter::set(100);
assert_eq!(100, Counter::next());
assert_eq!(101, Counter::next());
assert_eq!(102, Counter::next());
}
}