use core::sync::atomic::{AtomicU8, Ordering};
const RESERVED: u8 = 0;
const PUBLISHED: u8 = 1;
const RELEASED: u8 = 2;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum PmuResourceClaim {
Reserved,
Published,
}
#[derive(Debug)]
pub(crate) struct PmuResourceRelease {
state: AtomicU8,
}
impl PmuResourceRelease {
pub(crate) const fn new() -> Self {
Self {
state: AtomicU8::new(RESERVED),
}
}
pub(crate) fn is_released(&self) -> bool {
self.state.load(Ordering::Acquire) == RELEASED
}
pub(crate) fn publish(&self) -> bool {
self.state
.compare_exchange(RESERVED, PUBLISHED, Ordering::AcqRel, Ordering::Acquire)
.is_ok()
}
pub(crate) fn claim(&self) -> Option<PmuResourceClaim> {
let mut observed = self.state.load(Ordering::Acquire);
loop {
let claim = match observed {
RESERVED => PmuResourceClaim::Reserved,
PUBLISHED => PmuResourceClaim::Published,
RELEASED => return None,
_ => unreachable!("invalid PMU resource lifecycle state"),
};
match self.state.compare_exchange_weak(
observed,
RELEASED,
Ordering::AcqRel,
Ordering::Acquire,
) {
Ok(_) => return Some(claim),
Err(current) => observed = current,
}
}
}
}