Bugzilla – Bug 376
Mixing use of realtime simulator Schedule and Schedule now problematic
Last modified: 2008-10-27 08:20:07 UTC
Consider the following scenario (not using underlying real time clocks): Event A starts running at tA Schedule Event B for tA + tEpsilon long processing step tP consumes real-time tP ScheduleNow Event C This would result in the following sequence of events: Event A, Event C, Event B If you use ScheduleNow with an underlying realtime clock, and the time consumed by the the procesing step is small (tP < tEpsilon), the order of execution is unchanged. However, if tP > tEpsilon the executed event order changes to Event A, Event B, Event C In the real world tP may vary around tEpsilon and the event ordering may change unpredictably and incorrectly as system loads vary. There are cases where doing a ScheduleNow using the actual underlying realtime clock is required (to cause simulation time to advance in the presence of external events such as network packet reception). There are cases where using the underlying realtime clock can cause errors in situations where dependent events can change order. The current realtime simulator makes no distinction between scheduling operations that involve the realtime clock and those that don't. This leads to slippery situations. There need to be two kinds of scheduling methods: one set that respects time as models may assume using m_currentTs as a basis, and one set that works with the current realtime as a basis. How this works is tricky. The time to process event A can no longer affect the order of the events A, B and C. If we implement a separate {Schedule, ScheduleNow} and {ScheduleReal, ScheduleRealNow} the situation changes. The related events {A,B,C} use Schedule and ScheduleNow and are therefore using m_currentTs as a basis. The external device uses ScheduleRealNow and uses the current realtime as a basis. What we have then is an unrelated external event being scheduled for some time during the actual execution of the related events: Event A starts running at m_currentTs = tA, realtime ~ tA Schedule() Event B for absolute time tA + tEpsilon (based on m_currentTs) long processing step consumes real-time during event A execution Packet Reception queues event D for realtime tA < tR < tEpsilon ScheduleNow Event C (based on m_currentTs) = tA Here's what happens: 1. Event A is run at about realtime = tA. 2. Event B is inserted at the head of the queue for tA + tEpsilon at about realtime tA 3. Event A continues running for some time tP. Somewhere during the event, an external thread schedules an event for tA + tR (at the current realtime then) which is less than tA + tEpsilon, so this goes at the head of the event queue. 4. Event C is scheduled for m_currentTs = tA and so this goes to the head of the event queue. Event execution is as follows, Event A @ tA executes at realtime ~ tA Event C @ tA executes at realtime ~ tA plus tP (after event A) Event D @ tA + tR executes at realtime tA + tR Event B @ tA + tEpsilon The order of the events A, B, C is preserved. Event D is an unrelated "asynchronous" event that happens at some realtime before tA + tEpsilon You can see that if tA + tR > tA + tEpsilon (the reception event happens during the execution time of tA (where m_currentTs = tA) but at a realtime > tA + tEpsilon, the execution order of all events changes, but the ordering of the events scheduled by Schedule() and ScheduleNow() is preserved. Event A @ tA executes at realtime ~ tA Event C @ tA executes at realtime ~ tA plus tP (after event A) Event B @ tA + tEpsilon Event D @ tA + tR executes at realtime tA + tR This seems to me to be the right thing to do.
I would like to see a single ScheduleReal instead of ScheduleReal+ScheduleRealNow: ScheduleRealNow is purely syntactical sugar for ScheduleReal(Seconds (0.0)) and I can't imagine that we will have enough users of this piece of code to make this syntactical sugar very useful.
Not that it is a terribly big deal, but I think the two models, real and non-real, should be symmetric. I think the main use for the real-time call will be in the form of ScheduleRealNow(); and I think forcing the user (probably mostly me) to always call ScheduleReal(0) is just unnecessary obfuscation. I like syntactic sugar, since its purpose is to make my life easier. I like symmetrical interfaces since it means fewer exceptions to remember.
Created attachment 264 [details] Separate out simulator methods that can change time based on realtime clock.