pub struct Simulation<State, Time>{ /* private fields */ }Expand description
Contains the event queue and other state belonging to a simulation.
This form of simulation behaves very similarly to the serial::Simulation, but is easier to share across thread
boundaries for the sake of enabling events to divide-and-conquer parts of their execution.
The expected workflow for a Simulation is:
- Initialize a struct that implements
SimStateandSync. - Pass this struct and the start time to
new(). - Schedule at least one initial event.
- Call
run(). Handle any error it might return. - Use the
state()orstate_mut()accessors to finish processing the results.
A Simulation is Sync, and will also be Send if and only if the SimState implementation is Send.
Note: in the implementation of
Debug, scheduled events will be printed in an arbitrary order and the number oftotal_events_scheduledis over the entirety of the simulation run, as opposed to the number currently in queue.
Implementations§
Source§impl<State, Time> Simulation<State, Time>
impl<State, Time> Simulation<State, Time>
Sourcepub fn new(initial_state: State, start_time: Time) -> Self
pub fn new(initial_state: State, start_time: Time) -> Self
Initialize a Simulation instance with the provided starting state and an empty event queue, with clock set to the provided starting time.
Sourcepub fn run(&mut self) -> Result
pub fn run(&mut self) -> Result
Execute events from the priority queue, one at a time, in ascending order by execution time.
Follows this loop:
- Does
state.is_complete()return true? If so, returnOk(()). - Attempt to pop the next event from the queue. If there isn’t one, return
Ok(()). - Pass
&mut selftoevent.execute(). If execution results in an error, forward it to the caller; otherwise return to step 1.
§Errors
Errors may occur during execution of events, and if encountered here they will be passed back to the caller, unchanged. The two variants directly supported are:
Error::BackInTimemeans that client code attempted to schedule an event at some point in the simulation’s past. This error is a likely indicator that client code contains a logical bug, as most discrete-event simulations would never rewind their clocks.Error::BadExecutionwraps a client-generated error in a way that is type-safe to feed back through this method. To handle the underlying error, either unpack theBadExecutionor call itssource()method.
§Panics
This method requires the ability to lock the Mutex on the internal event queue to find the next event that
should be executed on each loop iteration. If that Mutex ever becomes poisoned, this method will panic.
Sourcepub fn schedule<EventType>(&self, event: EventType, time: Time) -> Resultwhere
EventType: Event<State, Time> + 'static,
pub fn schedule<EventType>(&self, event: EventType, time: Time) -> Resultwhere
EventType: Event<State, Time> + 'static,
Schedule the provided event at the specified time.
§Errors
If time is less than the current clock time on self, returns an Error::BackInTime to indicate the likely
presence of a logical bug at the call site, with no modifications to the queue.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub unsafe fn schedule_unchecked<EventType>(&self, event: EventType, time: Time)where
EventType: Event<State, Time> + 'static,
pub unsafe fn schedule_unchecked<EventType>(&self, event: EventType, time: Time)where
EventType: Event<State, Time> + 'static,
Schedule the provided event at the specified time. Assumes that the provided time is valid in the context of the client’s simulation.
§Safety
While this method cannot trigger undefined behaviors, scheduling an event for a time in the past is likely to be
a logical bug in client code. Generally, this method should only be invoked if the condition time >= clock is
already enforced at the call site through some other means. For example, adding a strictly positive offset to
the current clock time to get the time argument for the call.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub fn schedule_from_boxed(
&self,
event: Box<dyn Event<State, Time>>,
time: Time,
) -> Result
pub fn schedule_from_boxed( &self, event: Box<dyn Event<State, Time>>, time: Time, ) -> Result
Schedule the provided event at the specified time.
§Errors
If time is less than the current clock time on self, returns an Error::BackInTime to indicate the likely
presence of a logical bug at the call site, with no modifications to the queue.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub unsafe fn schedule_unchecked_from_boxed(
&self,
event: Box<dyn Event<State, Time>>,
time: Time,
)
pub unsafe fn schedule_unchecked_from_boxed( &self, event: Box<dyn Event<State, Time>>, time: Time, )
Schedule the provided event at the specified time. Assumes that the provided time is valid in the context of the client’s simulation.
§Safety
While this method cannot trigger undefined behaviors, scheduling an event for a time in the past is likely to be
a logical bug in client code. Generally, this method should only be invoked if the condition time >= clock is
already enforced at the call site through some other means. For example, adding a strictly positive offset to
the current clock time to get the time argument for the call.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub fn state_mut(&mut self) -> &mut State
pub fn state_mut(&mut self) -> &mut State
Get an exclusive reference to the simulation state.
Sourcepub fn current_time(&self) -> &Time
pub fn current_time(&self) -> &Time
Get a shared reference to the current simulation time.
Source§impl<State, Time> Simulation<State, Time>
impl<State, Time> Simulation<State, Time>
Sourcepub fn schedule_now<EventType>(&self, event: EventType) -> Resultwhere
EventType: Event<State, Time> + 'static,
pub fn schedule_now<EventType>(&self, event: EventType) -> Resultwhere
EventType: Event<State, Time> + 'static,
Schedule the provided event to execute at the current sim time. Events previously scheduled for “now” will still execute before this event does.
§Errors
If the result of calling Clone::clone on the current sim time results in a new value that is somehow less
than the current sim time, this method will return an Error::BackInTime. Note that such behavior is not
expected from implementations of Clone::clone in most cases.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub unsafe fn schedule_now_unchecked<EventType>(&self, event: EventType)where
EventType: Event<State, Time> + 'static,
pub unsafe fn schedule_now_unchecked<EventType>(&self, event: EventType)where
EventType: Event<State, Time> + 'static,
Schedule the provided event to execute at the current sim time. Events previously scheduled for “now” will still execute before this event does.
§Safety
This method cannot directly trigger undefined behaviors, but relies on client implementations of
Clone::clone producing new values of SimTime that are not less than the cloned receiver (i.e. the
current simulation time). If my_sim_time.clone().cmp(my_sim_time) != Ordering::Less is always true for your
chosen type, this method will be safe to call.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub fn schedule_now_from_boxed(
&self,
event: Box<dyn Event<State, Time>>,
) -> Result
pub fn schedule_now_from_boxed( &self, event: Box<dyn Event<State, Time>>, ) -> Result
Schedule the provided event to execute at the current sim time. Events previously scheduled for “now” will still execute before this event does.
§Errors
If the result of calling Clone::clone on the current sim time results in a new value that is somehow less
than the current sim time, this method will return an Error::BackInTime. Note that such behavior is not
expected from implementations of Clone::clone in most cases.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub unsafe fn schedule_now_unchecked_from_boxed(
&self,
event: Box<dyn Event<State, Time>>,
)
pub unsafe fn schedule_now_unchecked_from_boxed( &self, event: Box<dyn Event<State, Time>>, )
Schedule the provided event to execute at the current sim time. Events previously scheduled for “now” will still execute before this event does.
§Safety
This method cannot directly trigger undefined behaviors, but relies on client implementations of
Clone::clone producing new values of SimTime that are not less than the cloned receiver (i.e. the
current simulation time). If my_sim_time.clone().cmp(my_sim_time) != Ordering::Less is always true for your
chosen type, this method will be safe to call.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Source§impl<State, Time> Simulation<State, Time>
impl<State, Time> Simulation<State, Time>
Sourcepub fn schedule_with_delay<EventType>(
&self,
event: EventType,
delay: Time,
) -> Resultwhere
EventType: Event<State, Time> + 'static,
pub fn schedule_with_delay<EventType>(
&self,
event: EventType,
delay: Time,
) -> Resultwhere
EventType: Event<State, Time> + 'static,
Schedule the provided event after the specified delay. The event’s execution time will be equal to the result of
self.current_time().clone() + delay.
§Errors
If the calculated execution time is less than the current clock time on self, returns an Error::BackInTime
to indicate the likely presence of a logical bug at the call site, with no modifications to the queue.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub unsafe fn schedule_with_delay_unchecked<EventType>(
&self,
event: EventType,
delay: Time,
)where
EventType: Event<State, Time> + 'static,
pub unsafe fn schedule_with_delay_unchecked<EventType>(
&self,
event: EventType,
delay: Time,
)where
EventType: Event<State, Time> + 'static,
Schedule the provided event after the specified delay. The event’s execution time will be equal to the result of
self.current_time().clone() + delay.
§Safety
This method cannot directly trigger undefined behaviors, but relies on the provided delay being “nonnegative;”
in other words that self.current_time().cmp(self.current_time().clone() + delay) != Ordering::Greater should
always be true. If you are certain that is true for your type, this method will be safe to call. Alternatively,
you may call this method to intentionally schedule an event in the past if your use case truly calls for that.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub fn schedule_with_delay_from_boxed(
&self,
event: Box<dyn Event<State, Time>>,
delay: Time,
) -> Result
pub fn schedule_with_delay_from_boxed( &self, event: Box<dyn Event<State, Time>>, delay: Time, ) -> Result
Schedule the provided event after the specified delay. The event’s execution time will be equal to the result of
self.current_time().clone() + delay.
§Errors
If the calculated execution time is less than the current clock time on self, returns an Error::BackInTime
to indicate the likely presence of a logical bug at the call site, with no modifications to the queue.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.
Sourcepub unsafe fn schedule_with_delay_unchecked_from_boxed(
&self,
event: Box<dyn Event<State, Time>>,
delay: Time,
)
pub unsafe fn schedule_with_delay_unchecked_from_boxed( &self, event: Box<dyn Event<State, Time>>, delay: Time, )
Schedule the provided event after the specified delay. The event’s execution time will be equal to the result of
self.current_time().clone() + delay.
§Safety
This method cannot directly trigger undefined behaviors, but relies on the provided delay being “nonnegative;”
in other words that self.current_time().cmp(self.current_time().clone() + delay) != Ordering::Greater should
always be true. If you are certain that is true for your type, this method will be safe to call. Alternatively,
you may call this method to intentionally schedule an event in the past if your use case truly calls for that.
§Panics
This method requires the ability to lock the Mutex on the internal event queue. If that Mutex ever
becomes poisoned, this method will panic.