use std::sync::atomic::{AtomicU64, Ordering};
use super::Clock;
#[derive(Debug)]
pub struct MemClock {
counter: AtomicU64,
}
impl Clock for MemClock {
type IncrementError = std::convert::Infallible;
type WitnessError = std::convert::Infallible;
fn time(&self) -> super::Time {
super::Time(self.counter.load(Ordering::SeqCst))
}
fn increment(&mut self) -> Result<super::Time, Self::IncrementError> {
Ok(super::Time(self.counter.fetch_add(1, Ordering::SeqCst)))
}
fn witness(&mut self, time: super::Time) -> Result<(), Self::WitnessError> {
let current = self.time().0;
let other = time.0;
if other <= current {
return Ok(());
}
while self
.counter
.compare_exchange(current, other, Ordering::SeqCst, Ordering::SeqCst)
!= Ok(current)
{
}
Ok(())
}
}
impl Default for MemClock {
fn default() -> Self {
Self::new()
}
}
impl MemClock {
#[must_use]
pub fn new() -> Self {
Self {
counter: AtomicU64::new(1),
}
}
#[must_use]
pub fn new_with_value(value: u64) -> Self {
if value == 0 {
todo!("Read invalid value from persisted clock.")
}
Self {
counter: AtomicU64::new(value),
}
}
}
#[cfg(test)]
mod test {
use super::MemClock;
use crate::replica::entity::lamport::test::test_clock;
#[test]
fn test_mem_clock() {
let clock = MemClock::new();
test_clock(clock);
}
}