use std::fmt::Display;
use std::fmt::Formatter;
use std::num::NonZeroU64;
use std::sync::atomic::AtomicU64;
use std::sync::atomic::Ordering;
static NEXT_CLOCK_DOMAIN: AtomicU64 = AtomicU64::new(1);
#[inline(always)]
pub(crate) fn next_identifier_state(identifier: u64) -> Option<u64> {
NonZeroU64::new(identifier).map(|identifier| identifier.get().wrapping_add(1))
}
#[must_use = "the allocated domain identifier must initialize a clock domain"]
#[inline]
fn allocate_clock_domain_identifier(next: &AtomicU64) -> u64 {
next.fetch_update(Ordering::Relaxed, Ordering::Relaxed, next_identifier_state)
.expect("monotonic clock domain identifiers exhausted")
}
#[must_use = "clock domains should be retained to identify monotonic timelines"]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ClockDomain(
u64,
);
impl ClockDomain {
#[allow(clippy::new_without_default)]
#[inline(always)]
pub fn new() -> Self {
Self(allocate_clock_domain_identifier(&NEXT_CLOCK_DOMAIN))
}
}
impl Display for ClockDomain {
#[inline(always)]
fn fmt(&self, formatter: &mut Formatter<'_>) -> std::fmt::Result {
let Self(identifier) = self;
identifier.fmt(formatter)
}
}