use crate::is;
use crate::{MemHedgeCtrl, MemHedgeError, MemHedgeState, MemReplicaSlice};
#[doc = crate::_tags!(mem concurrency lifetime runtime)]
#[doc = crate::_doc_meta!{location("sys/mem/cell")}]
#[derive(Debug, Clone, Copy)]
pub struct MemHedgeRead<'a, 's, T, const N: usize> {
ctrl: &'a MemHedgeCtrl,
replicas: &'a MemReplicaSlice<'s, T, N>,
}
impl<'a, 's, T, const N: usize> MemHedgeRead<'a, 's, T, N> {
pub const fn new(ctrl: &'a MemHedgeCtrl, replicas: &'a MemReplicaSlice<'s, T, N>) -> Self {
Self { ctrl, replicas }
}
pub const fn ctrl(&self) -> &'a MemHedgeCtrl {
self.ctrl
}
pub const fn replicas(&self) -> &'a MemReplicaSlice<'s, T, N> {
self.replicas
}
pub fn arm(&self, logical_index: usize) -> Result<usize, MemHedgeError> {
is! { logical_index >= self.replicas.len(), return Err(MemHedgeError::OutOfBounds) }
self.ctrl.arm(logical_index)
}
pub fn clear(&self) {
self.ctrl.clear();
}
pub fn epoch(&self) -> usize {
self.ctrl.epoch()
}
pub fn logical_index(&self) -> usize {
self.ctrl.logical_index()
}
pub fn state(&self) -> MemHedgeState {
self.ctrl.state()
}
pub fn winner(&self) -> Option<usize> {
self.ctrl.winner()
}
pub fn read(&self) -> Result<&T, MemHedgeError> {
self.read_replica(0)
}
pub fn read_replica(&self, replica: usize) -> Result<&T, MemHedgeError> {
is! { self.state() == MemHedgeState::Idle, return Err(MemHedgeError::NotArmed) }
is! { replica >= N, return Err(MemHedgeError::InvalidReplica) }
let logical_index = self.logical_index();
self.replicas.get_replica(replica, logical_index).ok_or(MemHedgeError::OutOfBounds)
}
pub fn try_read_claim(&self, replica: usize) -> Result<Option<&T>, MemHedgeError> {
let value = self.read_replica(replica)?;
match self.ctrl.try_claim(replica)? {
true => Ok(Some(value)),
false => Ok(None),
}
}
}