mod clock;
mod monotonic_time;
mod ticker;
pub use tai_time::MonotonicTime;
pub use clock::{AutoSystemClock, Clock, NoClock, SyncStatus, SystemClock};
pub use ticker::{PeriodicTicker, Ticker};
pub(crate) use monotonic_time::TearableAtomicTime;
pub(crate) type AtomicTime = crate::util::sync_cell::SyncCell<TearableAtomicTime>;
pub(crate) type AtomicTimeReader = crate::util::sync_cell::SyncCellReader<TearableAtomicTime>;
pub trait Deadline {
fn into_time(self, now: MonotonicTime) -> MonotonicTime;
}
impl Deadline for std::time::Duration {
#[inline(always)]
fn into_time(self, now: MonotonicTime) -> MonotonicTime {
now + self
}
}
impl Deadline for MonotonicTime {
#[inline(always)]
fn into_time(self, _: MonotonicTime) -> MonotonicTime {
self
}
}
#[derive(Clone)]
pub struct ClockReader(AtomicTimeReader);
impl ClockReader {
pub(crate) fn from_atomic_time_reader(reader: &AtomicTimeReader) -> Self {
Self(reader.clone())
}
pub fn time(&self) -> MonotonicTime {
self.0.read()
}
}
impl std::fmt::Debug for ClockReader {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ClockReader").finish_non_exhaustive()
}
}
#[cfg(all(test, not(nexosim_loom)))]
mod tests {
use std::time::Duration;
use serde::{Deserialize, Serialize};
use crate::{
self as nexosim,
model::Model,
ports::EventSource,
simulation::{Mailbox, SimInit},
};
use super::*;
#[derive(Serialize, Deserialize)]
struct TestModel;
#[Model]
impl TestModel {
fn input(&mut self) {}
}
fn test_clock_reader(num_threads: usize) {
let model = TestModel;
let mbox = Mailbox::new();
let addr = mbox.address();
let t0 = MonotonicTime::EPOCH;
let mut bench = SimInit::with_num_threads(num_threads).add_model(model, mbox, "test");
let event_id = EventSource::new()
.connect(TestModel::input, &addr)
.register(&mut bench);
let reader = bench.clock_reader();
let mut simu = bench.init(t0).unwrap();
let scheduler = simu.scheduler();
scheduler
.schedule_event(Duration::from_millis(500), &event_id, ())
.unwrap();
assert_eq!(reader.time(), simu.time());
simu.step().unwrap();
assert_eq!(reader.time(), simu.time());
}
#[test]
fn clock_reader_st() {
test_clock_reader(1);
}
#[test]
fn clock_reader_mt() {
test_clock_reader(4);
}
}