use std::{ cell::Cell, fmt::{Debug, Formatter}, ops::{Add, BitAnd, BitOr, Sub}, }; #[derive(Default)] pub struct NumCell { t: Cell, } impl Debug for NumCell { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { self.t.get().fmt(f) } } impl NumCell { #[inline(always)] pub fn new(t: T) -> Self { Self { t: Cell::new(t) } } #[inline(always)] pub fn set(&self, n: T) { let _ = self.t.replace(n); } #[inline(always)] pub fn replace(&self, n: T) -> T { self.t.replace(n) } #[inline(always)] pub fn get(&self) -> T where T: Copy, { self.t.get() } #[inline(always)] pub fn fetch_add(&self, n: T) -> T where T: Copy + Add, { let res = self.t.get(); self.t.set(res + n); res } #[inline(always)] pub fn add_fetch(&self, n: T) -> T where T: Copy + Add, { let res = self.t.get() + n; self.t.set(res); res } #[inline(always)] pub fn fetch_sub(&self, n: T) -> T where T: Copy + Sub, { let res = self.t.get(); self.t.set(res - n); res } #[inline(always)] pub fn or_assign(&self, n: T) where T: Copy + BitOr, { self.t.set(self.t.get() | n); } #[inline(always)] pub fn and_assign(&self, n: T) where T: Copy + BitAnd, { self.t.set(self.t.get() & n); } #[inline(always)] pub fn is_zero(&self) -> bool where T: Eq + Copy + Default, { self.t.get() == T::default() } #[inline(always)] pub fn is_not_zero(&self) -> bool where T: Eq + Copy + Default, { !self.is_zero() } } impl + Copy> BitOr for &'_ NumCell { type Output = T; #[inline(always)] fn bitor(self, rhs: T) -> Self::Output { self.t.get() | rhs } } impl + Copy> BitAnd for &'_ NumCell { type Output = T; #[inline(always)] fn bitand(self, rhs: T) -> Self::Output { self.t.get() & rhs } }