use core::cell::Ref;
use core::marker::PhantomData;
use crate::datastore::{Storable, slot};
#[derive(Debug)]
pub struct InitializedReader<'a, T>
where
T: Storable + 'static,
{
waiter: slot::Waiter<'a, T>,
marker: PhantomData<fn(T)>,
}
impl<T> InitializedReader<'_, T>
where
T: Storable + 'static,
{
#[cfg_attr(feature = "veecle-telemetry", veecle_telemetry::instrument)]
pub fn read<U>(&self, f: impl FnOnce(&T::DataType) -> U) -> U {
self.waiter.read(|value| {
let value = value
.as_ref()
.expect("initialized reader should only access initialized values");
#[cfg(feature = "veecle-telemetry")]
veecle_telemetry::trace!("Slot read.", type_name = self.waiter.inner_type_name());
f(value)
})
}
pub fn read_cloned(&self) -> T::DataType
where
T::DataType: Clone,
{
self.read(|t| t.clone())
}
#[cfg_attr(feature = "veecle-telemetry", veecle_telemetry::instrument)]
pub async fn wait_for_update(&mut self) -> &mut Self {
self.waiter.wait().await;
self.waiter.update_generation();
self
}
}
impl<'a, T> InitializedReader<'a, T>
where
T: Storable + 'static,
{
pub(crate) fn new(waiter: slot::Waiter<'a, T>) -> Self {
Self {
waiter,
marker: Default::default(),
}
}
}
impl<T> super::combined_readers::Sealed for InitializedReader<'_, T> where T: Storable {}
impl<T> super::combined_readers::CombinableReader for InitializedReader<'_, T>
where
T: Storable,
{
type ToBeRead = T::DataType;
fn borrow(&self) -> Ref<'_, Self::ToBeRead> {
Ref::map(self.waiter.borrow(), |t| t.as_ref().unwrap())
}
async fn wait_for_update(&mut self) {
self.wait_for_update().await;
}
}
#[cfg(test)]
mod tests {
use core::pin::pin;
use futures::FutureExt;
use crate::datastore::{Reader, Slot, Storable, Writer, generational};
#[test]
fn read() {
#[derive(Eq, PartialEq, Debug, Clone, Storable)]
#[storable(crate = crate)]
struct Sensor(u8);
let source = pin!(generational::Source::new());
let slot = pin!(Slot::<Sensor>::new());
let mut writer = Writer::new(source.as_ref().waiter(), slot.as_ref());
let reader = Reader::from_slot(slot.as_ref());
assert!(reader.wait_init().now_or_never().is_none());
source.as_ref().increment_generation();
writer.write(Sensor(5)).now_or_never().unwrap();
let reader = Reader::from_slot(slot.as_ref())
.wait_init()
.now_or_never()
.unwrap();
assert_eq!(reader.read(|x: &Sensor| x.clone()), Sensor(5));
assert_eq!(reader.read_cloned(), Sensor(5));
}
#[test]
fn wait_for_update() {
#[derive(Eq, PartialEq, Debug, Clone, Storable)]
#[storable(crate = crate)]
struct Sensor(u8);
let source = pin!(generational::Source::new());
let slot = pin!(Slot::<Sensor>::new());
let mut writer = Writer::new(source.as_ref().waiter(), slot.as_ref());
let reader = Reader::from_slot(slot.as_ref());
source.as_ref().increment_generation();
writer.write(Sensor(1)).now_or_never().unwrap();
let mut reader = reader.wait_init().now_or_never().unwrap();
assert!(reader.wait_for_update().now_or_never().is_some());
assert!(reader.wait_for_update().now_or_never().is_none());
source.as_ref().increment_generation();
writer.write(Sensor(1)).now_or_never().unwrap();
reader
.wait_for_update()
.now_or_never()
.unwrap()
.read(|x| assert_eq!(x, &Sensor(1)));
}
#[test]
fn wait_init_wait_for_update() {
#[derive(Eq, PartialEq, Debug, Clone, Storable)]
#[storable(crate = crate)]
struct Sensor(u8);
let source = pin!(generational::Source::new());
let slot = pin!(Slot::<Sensor>::new());
let mut writer = Writer::new(source.as_ref().waiter(), slot.as_ref());
let reader = Reader::from_slot(slot.as_ref());
let mut wait_init_fut = pin!(reader.wait_init());
assert!(wait_init_fut.as_mut().now_or_never().is_none());
source.as_ref().increment_generation();
writer.write(Sensor(1)).now_or_never().unwrap();
let mut reader = wait_init_fut.now_or_never().unwrap();
reader
.wait_for_update()
.now_or_never()
.unwrap()
.read(|x| assert_eq!(x, &Sensor(1)));
}
}