use crate::sync::AtomicOp;
use core::marker::PhantomData;
use core::sync::atomic::Ordering;
use super::{Atomic, Discriminant};
pub struct Mutual<E: Discriminant>
where
E::Repr: AtomicOp + Into<usize> + TryFrom<usize>,
{
repr: <E::Repr as Atomic>::Atomic,
_phantom: PhantomData<E>,
}
impl<E: Discriminant> Default for Mutual<E>
where
<E as Discriminant>::Repr: AtomicOp + TryFrom<usize>,
<<E as Discriminant>::Repr as Atomic>::Atomic: Default,
{
fn default() -> Self {
Self {
repr: Default::default(),
_phantom: Default::default(),
}
}
}
impl<E: Discriminant> Mutual<E>
where
E::Repr: AtomicOp + Into<usize> + TryFrom<usize> + Copy + PartialEq,
{
pub const fn new() -> Self {
Self {
repr: E::Repr::new(),
_phantom: PhantomData,
}
}
pub fn set(&self, variant: E) {
E::Repr::store(&self.repr, variant.discriminant(), Ordering::Release);
}
pub fn is(&self, variant: &E) -> bool {
let current = E::Repr::load(&self.repr, Ordering::Acquire);
current == variant.discriminant()
}
pub fn compare_exchange(
&self,
expected: E,
new: E,
success: Ordering,
failure: Ordering,
) -> Result<E::Repr, E::Repr> {
E::Repr::compare_exchange(
&self.repr,
expected.discriminant(),
new.discriminant(),
success,
failure,
)
}
pub fn load(&self, order: Ordering) -> E::Repr {
E::Repr::load(&self.repr, order)
}
}