use std::sync::atomic::{AtomicU8, Ordering};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Color {
White = 0,
Gray = 1,
Black = 2,
}
impl From<u8> for Color {
fn from(value: u8) -> Self {
match value {
0 => Color::White,
1 => Color::Gray,
2 => Color::Black,
_ => Color::White,
}
}
}
pub struct AtomicColor {
inner: AtomicU8,
}
impl AtomicColor {
pub fn new(color: Color) -> Self {
Self {
inner: AtomicU8::new(color as u8),
}
}
fn load(&self, ordering: Ordering) -> Color {
Color::from(self.inner.load(ordering))
}
fn store(&self, color: Color, ordering: Ordering) {
self.inner.store(color as u8, ordering);
}
#[inline]
fn compare_exchange(
&self,
current: Color,
new: Color,
success: Ordering,
failure: Ordering,
) -> Result<Color, Color> {
self.inner
.compare_exchange(current as u8, new as u8, success, failure)
.map(Color::from)
.map_err(Color::from)
}
#[inline]
pub fn mark_white_to_gray(&self) -> bool {
self.compare_exchange(
Color::White,
Color::Gray,
Ordering::SeqCst,
Ordering::SeqCst,
)
.is_ok()
}
#[inline]
pub fn mark_black(&self) {
self.store(Color::Black, Ordering::Release);
}
#[inline]
pub fn reset_white(&self) {
self.store(Color::White, Ordering::Release);
}
#[inline]
pub fn is_white(&self) -> bool {
self.load(Ordering::Acquire) == Color::White
}
}