1use core::fmt;
4use core::sync::atomic::{AtomicUsize, Ordering};
5
6use crate::epoch::Epoch;
7
8use self::State::{Active, Inactive};
9
10const INACTIVE_BIT: usize = 0b1;
11
12#[derive(Debug)]
19pub struct ThreadState(AtomicUsize);
20
21impl ThreadState {
22 #[inline]
25 pub fn new(global_epoch: Epoch) -> Self {
26 Self(AtomicUsize::new(global_epoch.into_inner() | INACTIVE_BIT))
27 }
28
29 #[inline]
31 pub fn is_same(&self, other: &Self) -> bool {
32 self as *const Self == other as *const Self
33 }
34
35 #[inline]
48 pub fn load(&self, order: Ordering) -> (Epoch, State) {
49 let state = self.0.load(order);
50 (Epoch::with_epoch(state & !INACTIVE_BIT), State::from(state & INACTIVE_BIT == 0))
51 }
52
53 #[inline]
66 pub fn store(&self, epoch: Epoch, state: State, order: Ordering) {
67 match state {
68 Active => self.0.store(epoch.into_inner(), order),
69 Inactive => self.0.store(epoch.into_inner() | INACTIVE_BIT, order),
70 };
71 }
72}
73
74impl fmt::Display for ThreadState {
75 #[inline]
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 let (epoch, state) = self.load(Ordering::SeqCst);
78 write!(f, "epoch {}, state: {}", epoch, state)
79 }
80}
81
82#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
88pub enum State {
89 Active,
92 Inactive,
95}
96
97impl From<bool> for State {
98 #[inline]
99 fn from(is_active: bool) -> Self {
100 if is_active {
101 Active
102 } else {
103 Inactive
104 }
105 }
106}
107
108impl fmt::Display for State {
109 #[inline]
110 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
111 match *self {
112 Active => write!(f, "active"),
113 Inactive => write!(f, "inactive"),
114 }
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use std::sync::atomic::Ordering::Relaxed;
121
122 use crate::epoch::Epoch;
123
124 use super::{
125 State::{self, Active, Inactive},
126 ThreadState,
127 };
128
129 #[test]
130 fn thread_state_equality() {
131 let epoch = Epoch::with_epoch(128);
132 let thread_state = ThreadState::new(epoch);
133 let other_thread_state = ThreadState::new(epoch);
134
135 assert!(thread_state.is_same(&thread_state));
136 assert!(!thread_state.is_same(&other_thread_state));
137 }
138
139 #[test]
140 fn load_thread_state() {
141 let init_epoch = Epoch::with_epoch(128);
142 let thread_state = ThreadState::new(init_epoch);
143 let (epoch, state) = thread_state.load(Relaxed);
144
145 assert_eq!(init_epoch, epoch);
146 assert_eq!(state, Inactive);
147 }
148
149 #[test]
150 fn store_thread_state() {
151 let init_epoch = Epoch::with_epoch(1000);
152 let thread_state = ThreadState::new(init_epoch);
153 let next_epoch = init_epoch + 1;
154
155 thread_state.store(next_epoch, Active, Relaxed);
156 let (epoch, state) = thread_state.load(Relaxed);
157
158 assert_eq!(epoch, next_epoch);
159 assert_eq!(state, Active);
160 }
161
162 #[test]
163 fn from_bool() {
164 assert_eq!(Active, State::from(true));
165 assert_eq!(Inactive, State::from(false));
166 }
167}