forked from ROMEO/nexosim
Merge step_by and step_until into a unique method
Now that `step_by` returns an error anyway (it was unfaillible before), there is no more incentive to keep it as a separate method. The `step_until` method now accepts an `impl Deadline`, which covers both cases (`Duration` and `MonotonicTime`).
This commit is contained in:
@ -118,7 +118,9 @@ impl ControllerService {
|
||||
"the specified deadline lies in the past",
|
||||
))?;
|
||||
|
||||
simulation.step_by(duration).map_err(map_execution_error)?;
|
||||
simulation
|
||||
.step_until(duration)
|
||||
.map_err(map_execution_error)?;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -246,8 +246,8 @@
|
||||
//!
|
||||
//! 1. by advancing time, either until the next scheduled event with
|
||||
//! [`Simulation::step()`](simulation::Simulation::step), or until a specific
|
||||
//! deadline using for instance
|
||||
//! [`Simulation::step_by()`](simulation::Simulation::step_by).
|
||||
//! deadline with
|
||||
//! [`Simulation::step_until()`](simulation::Simulation::step_until).
|
||||
//! 2. by sending events or queries without advancing simulation time, using
|
||||
//! [`Simulation::process_event()`](simulation::Simulation::process_event) or
|
||||
//! [`Simulation::send_query()`](simulation::Simulation::process_query),
|
||||
|
@ -122,9 +122,7 @@ mod scheduler;
|
||||
mod sim_init;
|
||||
|
||||
pub use mailbox::{Address, Mailbox};
|
||||
pub use scheduler::{
|
||||
Action, ActionKey, AutoActionKey, Deadline, LocalScheduler, Scheduler, SchedulingError,
|
||||
};
|
||||
pub use scheduler::{Action, ActionKey, AutoActionKey, LocalScheduler, Scheduler, SchedulingError};
|
||||
pub(crate) use scheduler::{
|
||||
KeyedOnceAction, KeyedPeriodicAction, OnceAction, PeriodicAction, SchedulerQueue,
|
||||
};
|
||||
@ -148,7 +146,7 @@ use crate::channel::ChannelObserver;
|
||||
use crate::executor::{Executor, ExecutorError, Signal};
|
||||
use crate::model::{BuildContext, Context, Model, ProtoModel};
|
||||
use crate::ports::{InputFn, ReplierFn};
|
||||
use crate::time::{AtomicTime, Clock, MonotonicTime, SyncStatus};
|
||||
use crate::time::{AtomicTime, Clock, Deadline, MonotonicTime, SyncStatus};
|
||||
use crate::util::seq_futures::SeqFuture;
|
||||
use crate::util::slot;
|
||||
|
||||
@ -189,9 +187,8 @@ thread_local! { pub(crate) static CURRENT_MODEL_ID: Cell<ModelId> = const { Cell
|
||||
/// desired wall clock time, and finally
|
||||
/// 3. run all computations scheduled for the new simulation time.
|
||||
///
|
||||
/// The [`step_by()`](Simulation::step_by) and
|
||||
/// [`step_until()`](Simulation::step_until) methods operate similarly but
|
||||
/// iterate until the target simulation time has been reached.
|
||||
/// The [`step_until()`](Simulation::step_until) method operates similarly but
|
||||
/// iterates until the target simulation time has been reached.
|
||||
pub struct Simulation {
|
||||
executor: Executor,
|
||||
scheduler_queue: Arc<Mutex<SchedulerQueue>>,
|
||||
@ -260,19 +257,6 @@ impl Simulation {
|
||||
self.step_to_next_bounded(MonotonicTime::MAX).map(|_| ())
|
||||
}
|
||||
|
||||
/// Iteratively advances the simulation time by the specified duration, as
|
||||
/// if by calling [`Simulation::step()`] repeatedly.
|
||||
///
|
||||
/// This method blocks until all events scheduled up to the specified target
|
||||
/// time have completed. The simulation time upon completion is equal to the
|
||||
/// initial simulation time incremented by the specified duration, whether
|
||||
/// or not an event was scheduled for that time.
|
||||
pub fn step_by(&mut self, duration: Duration) -> Result<(), ExecutionError> {
|
||||
let target_time = self.time.read() + duration;
|
||||
|
||||
self.step_until_unchecked(target_time)
|
||||
}
|
||||
|
||||
/// Iteratively advances the simulation time until the specified deadline,
|
||||
/// as if by calling [`Simulation::step()`] repeatedly.
|
||||
///
|
||||
@ -280,8 +264,10 @@ impl Simulation {
|
||||
/// time have completed. The simulation time upon completion is equal to the
|
||||
/// specified target time, whether or not an event was scheduled for that
|
||||
/// time.
|
||||
pub fn step_until(&mut self, target_time: MonotonicTime) -> Result<(), ExecutionError> {
|
||||
if self.time.read() >= target_time {
|
||||
pub fn step_until(&mut self, deadline: impl Deadline) -> Result<(), ExecutionError> {
|
||||
let now = self.time.read();
|
||||
let target_time = deadline.into_time(now);
|
||||
if target_time < now {
|
||||
return Err(ExecutionError::InvalidDeadline(target_time));
|
||||
}
|
||||
self.step_until_unchecked(target_time)
|
||||
|
@ -18,7 +18,7 @@ use crate::executor::Executor;
|
||||
use crate::model::Model;
|
||||
use crate::ports::InputFn;
|
||||
use crate::simulation::Address;
|
||||
use crate::time::{AtomicTimeReader, MonotonicTime};
|
||||
use crate::time::{AtomicTimeReader, Deadline, MonotonicTime};
|
||||
use crate::util::priority_queue::PriorityQueue;
|
||||
|
||||
/// Scheduler.
|
||||
@ -557,30 +557,6 @@ impl<M: Model> fmt::Debug for LocalScheduler<M> {
|
||||
// control their relative order of execution.
|
||||
pub(crate) type SchedulerQueue = PriorityQueue<(MonotonicTime, usize), Action>;
|
||||
|
||||
/// Trait abstracting over time-absolute and time-relative deadlines.
|
||||
///
|
||||
/// This trait is implemented by [`std::time::Duration`] and
|
||||
/// [`MonotonicTime`].
|
||||
pub trait Deadline {
|
||||
/// Make this deadline into an absolute timestamp, using the provided
|
||||
/// current time as a reference.
|
||||
fn into_time(self, now: MonotonicTime) -> MonotonicTime;
|
||||
}
|
||||
|
||||
impl Deadline for 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
|
||||
}
|
||||
}
|
||||
|
||||
/// Managed handle to a scheduled action.
|
||||
///
|
||||
/// An `AutoActionKey` is a managed handle to a scheduled action that cancels
|
||||
|
@ -55,3 +55,27 @@ 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>;
|
||||
|
||||
/// Trait abstracting over time-absolute and time-relative deadlines.
|
||||
///
|
||||
/// This trait is implemented by [`std::time::Duration`] and
|
||||
/// [`MonotonicTime`].
|
||||
pub trait Deadline {
|
||||
/// Make this deadline into an absolute timestamp, using the provided
|
||||
/// current time as a reference.
|
||||
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
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user