Distinguish "real" from maintenance events; track "real" high water mark to stop simulator
(For background see the discussion in #237)
In many models we can distinguish two flavors of events:
- "Real" events, representing the real work of the model, such as sending/receiving data packets.
- "Maintenance" events, representing actions required by the protocol, independent of any "real" work done. These are things like "Hello" messages, "keep-alive", ..., in proactive protocols.
By default the simulator will stop when there are no more events in the queue. If you use a protocol which has maintenance events you have to set the simulator stop time explicitly, otherwise the maintenance events will keep the simulator running forever.
If we had a way to distinguish "real" from "maintenance" events when we schedule them, the simulator could track the "high water mark": the largest timestamp of all "real" events, then use this to decide to stop automatically.
So the task here is
- Define a mechanism to label events as "maintenance"; the default would be "real" events. Perhaps
class Simulator
{
...
enum EventRunType
{
MustRun, /**< Event must run before stopping. */
AsRequired /**< Run event when encountered, but stopping before this executes is allowed. */
}
}; // class Simulator
void SimulatorImpl::Schedule (Time delay, Event ev, Simulator::EventRunType run = Simulator::MustRun);
- Track the high water mark of real events in the Scheduler
class Scheduler
{
...
virtual void Insert (const Event &ev, Simulator::EventStopType stop) = 0;
virtual Time GetLatestRealEventTime (void) = 0;
}; // class Scheduler
- Change the Schedulers to check the high water mark relative to the next event, to decide if there any more "real" events. The SimulatorImpl's check Scheduler::IsEmpty:
while (!m_events->IsEmpty () && !m_stop) {...
, so suggest changing the logic there:
class MapScheduler
{
...
virtual bool IsEmpty (void) const
{
if (m_list.empty ())
{
return true;
}
uint64_t nextTs = PeekNext ().key.m_ts;
if (nextTx > m_latestRealTs)
{
return true;
}
return false;
}
Perhaps consider changing the function name IsEmpty()
to HaveMustRunEvents()