use crate::error::CRDTResult;
use crate::memory::MemoryConfig;
use crate::traits::CRDT;
pub trait RealTimeCRDT<C: MemoryConfig>: CRDT<C> {
const MAX_MERGE_CYCLES: u32;
const MAX_VALIDATE_CYCLES: u32;
const MAX_SERIALIZE_CYCLES: u32;
fn merge_bounded(&mut self, other: &Self) -> CRDTResult<()>;
fn validate_bounded(&self) -> CRDTResult<()>;
fn merge_wcet(&self) -> u32 {
Self::MAX_MERGE_CYCLES
}
fn validate_wcet(&self) -> u32 {
Self::MAX_VALIDATE_CYCLES
}
fn can_meet_deadline(&self, operation: RTOperation, deadline_cycles: u32) -> bool {
let wcet = match operation {
RTOperation::Merge => self.merge_wcet(),
RTOperation::Validate => self.validate_wcet(),
RTOperation::Serialize => Self::MAX_SERIALIZE_CYCLES,
};
wcet <= deadline_cycles
}
fn remaining_budget(&self) -> Option<u32>;
fn set_budget(&mut self, cycles: u32);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RTOperation {
Merge,
Validate,
Serialize,
}
pub trait InterruptSafeCRDT<C: MemoryConfig>: RealTimeCRDT<C> {
fn atomic_merge(&mut self, other: &Self) -> CRDTResult<()>;
fn atomic_read<F, R>(&self, f: F) -> R
where
F: FnOnce(&Self) -> R;
fn atomic_write<F>(&mut self, f: F) -> CRDTResult<()>
where
F: FnOnce(&mut Self) -> CRDTResult<()>;
fn is_locked(&self) -> bool;
fn max_interrupt_latency(&self) -> u32;
}
pub trait PrioritizedCRDT<C: MemoryConfig>: RealTimeCRDT<C> {
type Priority: PartialOrd + Copy;
fn merge_with_priority(&mut self, other: &Self, priority: Self::Priority) -> CRDTResult<()>;
fn can_preempt(&self, priority: Self::Priority) -> bool;
fn current_priority(&self) -> Option<Self::Priority>;
fn set_priority(&mut self, priority: Self::Priority);
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::CRDTError;
use crate::memory::DefaultConfig;
struct MockRTCRDT {
value: u32,
budget: Option<u32>,
}
impl CRDT<DefaultConfig> for MockRTCRDT {
type Error = CRDTError;
fn merge(&mut self, other: &Self) -> CRDTResult<()> {
self.value = self.value.max(other.value);
Ok(())
}
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
fn size_bytes(&self) -> usize {
core::mem::size_of::<u32>()
}
fn validate(&self) -> CRDTResult<()> {
Ok(())
}
fn state_hash(&self) -> u32 {
self.value
}
fn can_merge(&self, _other: &Self) -> bool {
true
}
}
impl RealTimeCRDT<DefaultConfig> for MockRTCRDT {
const MAX_MERGE_CYCLES: u32 = 100;
const MAX_VALIDATE_CYCLES: u32 = 50;
const MAX_SERIALIZE_CYCLES: u32 = 75;
fn merge_bounded(&mut self, other: &Self) -> CRDTResult<()> {
self.merge(other)
}
fn validate_bounded(&self) -> CRDTResult<()> {
self.validate()
}
fn remaining_budget(&self) -> Option<u32> {
self.budget
}
fn set_budget(&mut self, cycles: u32) {
self.budget = Some(cycles);
}
}
#[test]
fn test_realtime_crdt() {
let mut crdt = MockRTCRDT {
value: 10,
budget: None,
};
assert_eq!(crdt.merge_wcet(), 100);
assert_eq!(crdt.validate_wcet(), 50);
assert!(crdt.can_meet_deadline(RTOperation::Merge, 150));
assert!(!crdt.can_meet_deadline(RTOperation::Merge, 50));
crdt.set_budget(1000);
assert_eq!(crdt.remaining_budget(), Some(1000));
}
}