use std::sync::Mutex;
use sim_kernel::{Error, Result};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CellSnapshot<T> {
pub value: T,
pub version: u64,
}
pub struct StreamCell<T> {
state: Mutex<CellState<T>>,
}
struct CellState<T> {
value: T,
version: u64,
}
pub fn stream_cell<T>(value: T) -> StreamCell<T> {
StreamCell::new(value)
}
impl<T> StreamCell<T> {
pub fn new(value: T) -> Self {
Self {
state: Mutex::new(CellState { value, version: 0 }),
}
}
}
impl<T: Clone> StreamCell<T> {
pub fn get(&self) -> Result<CellSnapshot<T>> {
let state = self
.state
.lock()
.map_err(|_| Error::PoisonedLock("stream cell"))?;
Ok(CellSnapshot {
value: state.value.clone(),
version: state.version,
})
}
pub fn set(&self, value: T, expected_version: u64) -> Result<u64> {
let mut state = self
.state
.lock()
.map_err(|_| Error::PoisonedLock("stream cell"))?;
if state.version != expected_version {
return Err(Error::Eval(format!(
"stale stream cell version: expected {expected_version}, current {}",
state.version
)));
}
state.value = value;
state.version = state.version.saturating_add(1);
Ok(state.version)
}
}