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