1use std::sync::atomic::{AtomicU32, Ordering};
8
9use serde::Serialize;
10
11#[derive(Debug, Clone, Serialize)]
13pub struct Handle {
14 next: u32,
15 first: u32,
16}
17
18impl Handle {
19 pub fn new(first: u32) -> Handle {
21 Handle { next: first, first }
22 }
23
24 #[allow(clippy::should_implement_trait)]
27 pub fn next(&mut self) -> u32 {
28 let next = self.next;
29 if self.next == u32::MAX {
31 self.next = self.first;
32 } else {
33 self.next += 1;
34 }
35 next
36 }
37
38 pub fn peek_next(&self) -> u32 {
40 self.next
41 }
42
43 pub fn set_next(&mut self, next: u32) {
45 self.next = next;
46 }
47
48 pub fn reset(&mut self) {
50 self.set_next(self.first);
51 }
52}
53
54#[derive(Debug)]
56pub struct AtomicHandle {
57 next: AtomicU32,
58 first: u32,
59}
60
61impl AtomicHandle {
62 pub fn new(first: u32) -> Self {
65 Self {
66 next: AtomicU32::new(first),
67 first,
68 }
69 }
70
71 pub fn next(&self) -> u32 {
73 let mut val = self.next.fetch_add(1, Ordering::Relaxed);
74
75 while val < self.first {
76 match self.next.compare_exchange(
78 val + 1,
79 self.first + 1,
80 Ordering::Relaxed,
81 Ordering::Relaxed,
82 ) {
83 Ok(_) => val = self.first,
85 Err(v) => {
86 if v >= self.first {
87 val = self.next.fetch_add(1, Ordering::Relaxed);
88 } else {
89 val = v;
90 }
91 }
92 }
93 }
94 val
95 }
96
97 pub fn set_next(&self, next: u32) {
99 debug_assert!(next >= self.first);
100 self.next.store(next, Ordering::Relaxed);
101 }
102
103 pub fn reset(&self) {
105 self.set_next(self.first);
106 }
107}
108
109#[test]
110fn handle_increment() {
111 let mut h = Handle::new(0);
113 assert_eq!(h.next(), 0);
114 assert_eq!(h.next(), 1);
115 assert_eq!(h.next(), 2);
116 let mut h = Handle::new(100);
117 assert_eq!(h.next(), 100);
118 assert_eq!(h.next(), 101);
119}
120
121#[test]
122fn handle_wrap() {
123 let mut h = Handle::new(u32::MAX - 2);
125 assert_eq!(h.next(), u32::MAX - 2);
126 assert_eq!(h.next(), u32::MAX - 1);
127 assert_eq!(h.next(), u32::MAX);
128 assert_eq!(h.next(), u32::MAX - 2);
129}
130
131#[test]
132fn atomic_handle_increment() {
133 let h = AtomicHandle::new(0);
135 assert_eq!(h.next(), 0);
136 assert_eq!(h.next(), 1);
137 assert_eq!(h.next(), 2);
138 let h = AtomicHandle::new(100);
139 assert_eq!(h.next(), 100);
140 assert_eq!(h.next(), 101);
141}
142
143#[test]
144fn atomic_handle_wrap() {
145 let h = AtomicHandle::new(u32::MAX - 2);
147 assert_eq!(h.next(), u32::MAX - 2);
148 assert_eq!(h.next(), u32::MAX - 1);
149 assert_eq!(h.next(), u32::MAX);
150 assert_eq!(h.next(), u32::MAX - 2);
151}