sim.engine
Class Schedule

java.lang.Object
  extended bysim.engine.Schedule
All Implemented Interfaces:
java.io.Serializable

public class Schedule
extends java.lang.Object
implements java.io.Serializable

Schedule defines a scheduling queue in which events can be scheduled to occur after some number of "ticks" of a clock which the schedule maintains. The current tick is given by the time() method. If the current tick is BEFORE_SIMULATION (0), then the schedule is set to the "time before time" (the schedule hasn't started running yet). If the current tick is AFTER_SIMULATION (9218868437227405312), then the schedule has run out of time. EPOCH (1) is defined as the first timestep after BEFORE_SIMULATION -- it's the first timestep for which you can legally schedule a value.

An event is defined as a Steppable object. You can schedule events to either occur a single time or to occur repeatedly at some interval. If the event occurs repeatedly, the schedule will provide you with a Stoppable object on which you can call stop() to cancel all future repeats of the event.

The schedule is pulsed by calling its step(...) method. Each pulse, the schedule finds the next tick in which events are scheduled, moves ahead to that tick, and then calls all the events scheduled at that tick. Multiple events may be scheduled for the same clock tick. Events at a tick are further subdivided and scheduled according to their ordering. You specify the number of orderings in the constructor, and can't change them thereafter. If you specify N orderings, then the ordering values are 0 ... N-1. Objects for scheduled for lower orderings in a given time tick will be executed before objects with higher orderings for the same time tick. If objects are scheduled for the same time tick and have the same ordering value, their execution will be randomly ordered with respect to one another.

You may not schedule events to occur on or before BEFORE_SIMULATION (tick 0). Likewise, you may not schedule events to occur on or after AFTER_SIMULATION (tick 9218868437227405312). This gives you 9,218,868,437,227,405,311 timesteps to play with; we hope that's sufficient resolution for your simulation.

Schedule is synchronized and threadsafe. It's easy enough to de-synchronize the schedule by hand if you would like to. In the worst case (schedule a single repeated steppable that does nothing), a synchronized schedule runs at 2/3 the speed of an unsynchronized schedule. In a typical case (such as HeatBugs), the difference between a synchronized and an unsynchronized schedule is less than 5% efficiency loss if it's visible at all.

You can get the number of times that step(...) has been called on the schedule by calling the getSteps() method. This value is incremented just as the Schedule exits its step(...) method and only if the method returned true. Additionally, you can get a string version of the current time with the getTimestamp(...) method.

Using a Real-Valued Schedule

Schedule also has rudimentary facilities for use in pseudo-"real-valued" timesteps rather than discrete ones. This means that you can submit and receive time values as doubles rather than as longs. In this case, BEFORE_SIMULATION = 0.0 and AFTER_SIMULATION = +infinity. You schedule values in "real time" by converting your desired double-valued "times" to and from long ticks using toReals(...) and fromReals(...). These will come up with equivalent long values for your double such that if d1 < d2, then fromReals(d1) < fromReals(d2). Understand that this is not a cast: for example, fromReals(9.0) == 4621256167635550208. Your only guarantee is that if you convert your timestamps toReals() and fromReals(), they'll be ordered in the same way that your real-valued "desired" timestamps are ordered. Also note that NaN will always be an invalid timestamp.

You have to be careful using a real-valued schedule. Notably, you should not use any variant of scheduleRepeating(...) as they will not work correctly. To schedule events to occur repeatedly, the events will have to reschedule themselves. Further, take care to note that real values lose resolution as time goes by. Thus while you can distinguish between 0.000001 and 0.000002, you cannot distinguish between C+0.000001 and C+0.000002, where C is some large constant. This mostly will bite you if you schedule for a real-valued event at time T+1.0, but it turns out that T+1.0 rounds to T (the current time) in the schedule. In this case the event will not be scheduled. So be careful to check to make certain that your schedule(...) calls always return true.

See Also:
Serialized Form

Field Summary
static long AFTER_SIMULATION
           
static long BEFORE_SIMULATION
           
static long EPOCH
           
protected  Steppable[][] next
           
protected  int[] numNext
           
protected  int[] numSubsteps
           
protected  Heap[] queue
           
protected  long steps
           
protected  Steppable[][] substeps
           
protected  long time
           
 
Constructor Summary
Schedule()
          Creates a Schedule with a single order
Schedule(int numOrders)
           
 
Method Summary
protected  boolean _scheduleComplete()
           
 long fromReals(double time)
          Converts the reals "time" value into a long tick value -- this is NOT a cast.
 long getSteps()
           
 java.lang.String getTimestamp(long time, java.lang.String beforeSimulationString, java.lang.String afterSimulationString)
          Returns a given time in string format.
 java.lang.String getTimestamp(java.lang.String beforeSimulationString, java.lang.String afterSimulationString)
          Returns the current time in string format.
protected  Steppable[] increaseSubsteps(Steppable[] substeps)
           
protected  Steppable[] increaseSubsteps(Steppable[] substeps, int n)
           
 void reset()
          Empties out the schedule and resets it to a pristine state BEFORE_SIMULATION, with steps = 0.
protected  void resetQueues(int numOrders)
           
 boolean scheduleComplete()
          Returns true if the schedule has nothing left to do.
 boolean scheduleOnce(long time, int ordering, Steppable event)
          If the current time is less than the time requested, and the event is valid, schedules the event to occur at the requested time, placed in the 'first' queue, and returns TRUE.
 boolean scheduleOnce(long time, Steppable event)
          If the current time is less than the time requested, 0 ordering, and the event is valid, schedules the event to occur at the requested time and returns TRUE.
 boolean scheduleOnce(Steppable event)
          Schedules the event to occur at the next clock tick, 0 ordering.
 Stoppable scheduleRepeating(long time, int ordering, Steppable event)
          If the event is valid, and the current time is less than time, schedules the event to occur once every clock tick starting at time, with the given ordering, and returns a Stoppable, else returns null.
 Stoppable scheduleRepeating(long time, int ordering, Steppable event, long interval)
          If the event is valid, and the current time is less than time, schedules the event to occur once every interval's worth of clock ticks starting at time, with the given ordering, and returns a Stoppable, else returns null.
 Stoppable scheduleRepeating(long time, Steppable event)
          If the event is valid, and the current time is less than time, schedules the event to occur once every clock tick starting at time, 0 ordering, and returns a Steppable, else returns null.
 Stoppable scheduleRepeating(long time, Steppable event, long interval)
          If the event is valid, and the current time is less than time, schedules the event to occur once every interval's worth of clock ticks starting at time, 0 ordering, and returns a Stoppable, else returns null.
 Stoppable scheduleRepeating(Steppable event)
          If the event is valid, and the current time is valid, schedules the event to occur once every clock tick starting at the next clock tick, 0 ordering, and returns a Stoppable, else returns null.
 Stoppable scheduleRepeating(Steppable event, long interval)
          If the event is valid, and the current time is valid, schedules the event to occur once every interval's worth of clock ticks starting at the next clock tick, 0 ordering, and returns a Steppable, else returns null.
 boolean step(SimState state)
          Steps the schedule, gathering and ordering all the items to step on the next time step (skipping blank time steps), and then stepping all of them in the decided order.
 long time()
           
 double toReals(long time)
          Converts the long tick value into a reals "time" value (as a double) -- this is NOT a cast.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

BEFORE_SIMULATION

public static final long BEFORE_SIMULATION
See Also:
Constant Field Values

EPOCH

public static final long EPOCH
See Also:
Constant Field Values

AFTER_SIMULATION

public static final long AFTER_SIMULATION
See Also:
Constant Field Values

queue

protected Heap[] queue

next

protected Steppable[][] next

numNext

protected int[] numNext

substeps

protected Steppable[][] substeps

numSubsteps

protected int[] numSubsteps

time

protected long time

steps

protected long steps
Constructor Detail

Schedule

public Schedule(int numOrders)

Schedule

public Schedule()
Creates a Schedule with a single order

Method Detail

resetQueues

protected void resetQueues(int numOrders)

time

public long time()

getTimestamp

public java.lang.String getTimestamp(java.lang.String beforeSimulationString,
                                     java.lang.String afterSimulationString)
Returns the current time in string format. If the time is BEFORE_SIMULATION, then beforeSimulationString is returned. If the time is AFTER_SIMULATION, then afterSimulationString is returned. Otherwise a numerical representation of the time is returned.


getTimestamp

public java.lang.String getTimestamp(long time,
                                     java.lang.String beforeSimulationString,
                                     java.lang.String afterSimulationString)
Returns a given time in string format. If the time is BEFORE_SIMULATION, then beforeSimulationString is returned. If the time is AFTER_SIMULATION, then afterSimulationString is returned. Otherwise a numerical representation of the time is returned.


getSteps

public long getSteps()

toReals

public double toReals(long time)
Converts the long tick value into a reals "time" value (as a double) -- this is NOT a cast. If you use doubles, you should ONLY use doubles -- do not mix them with longs. See the warning in the class documentation. We can just convert bits to bits because the half-open long range (0 ... 9218868437227405312L] is equivalent to the half-open double range (0 ... +infinity]. NaN values exist outside this range, so they're not a problem.


fromReals

public long fromReals(double time)
Converts the reals "time" value into a long tick value -- this is NOT a cast. If you use doubles, you should ONLY use doubles -- do not mix them with longs. See the warning in the class documentation. We can just convert bits to bits because the half-open long range (0 ... 9218868437227405312L] is equivalent to the half-open double range (0 ... +infinity]. NaN values exist outside this range, so they're not a problem.


increaseSubsteps

protected Steppable[] increaseSubsteps(Steppable[] substeps)

increaseSubsteps

protected Steppable[] increaseSubsteps(Steppable[] substeps,
                                       int n)

reset

public void reset()
Empties out the schedule and resets it to a pristine state BEFORE_SIMULATION, with steps = 0.


scheduleComplete

public boolean scheduleComplete()
Returns true if the schedule has nothing left to do.


_scheduleComplete

protected boolean _scheduleComplete()

step

public boolean step(SimState state)
Steps the schedule, gathering and ordering all the items to step on the next time step (skipping blank time steps), and then stepping all of them in the decided order. Returns FALSE if nothing was stepped -- the schedule is exhausted or time has run out.


scheduleOnce

public boolean scheduleOnce(Steppable event)
Schedules the event to occur at the next clock tick, 0 ordering. If this is a valid time and event, schedules the event and returns TRUE, else returns FALSE.


scheduleOnce

public boolean scheduleOnce(long time,
                            Steppable event)
If the current time is less than the time requested, 0 ordering, and the event is valid, schedules the event to occur at the requested time and returns TRUE. Else returns FALSE.


scheduleOnce

public boolean scheduleOnce(long time,
                            int ordering,
                            Steppable event)
If the current time is less than the time requested, and the event is valid, schedules the event to occur at the requested time, placed in the 'first' queue, and returns TRUE. Else returns FALSE.


scheduleRepeating

public Stoppable scheduleRepeating(Steppable event)
If the event is valid, and the current time is valid, schedules the event to occur once every clock tick starting at the next clock tick, 0 ordering, and returns a Stoppable, else returns null. Returns a Stoppable which you can use to stop the repeated scheduling from occuring any more.

Note that calling stop() on the Stoppable will not only stop the repeating, but will also make the Schedule completely forget (lose the pointer to) the Steppable scheduled here. This is particularly useful if you need to make the Schedule NOT serialize certain Steppable objects. Do not use this with a real-valued schedule.


scheduleRepeating

public Stoppable scheduleRepeating(Steppable event,
                                   long interval)
If the event is valid, and the current time is valid, schedules the event to occur once every interval's worth of clock ticks starting at the next clock tick, 0 ordering, and returns a Steppable, else returns null. Returns a Stoppable which you can use to stop the repeated scheduling from occuring any more.

Note that calling stop() on the Stoppable will not only stop the repeating, but will also make the Schedule completely forget (lose the pointer to) the Steppable scheduled here. This is particularly useful if you need to make the Schedule NOT serialize certain Steppable objects. Do not use this with a real-valued schedule.


scheduleRepeating

public Stoppable scheduleRepeating(long time,
                                   Steppable event)
If the event is valid, and the current time is less than time, schedules the event to occur once every clock tick starting at time, 0 ordering, and returns a Steppable, else returns null. Returns a Stoppable which you can use to stop the repeated scheduling from occuring any more.

Note that calling stop() on the Stoppable will not only stop the repeating, but will also make the Schedule completely forget (lose the pointer to) the Steppable scheduled here. This is particularly useful if you need to make the Schedule NOT serialize certain Steppable objects. Do not use this with a real-valued schedule.


scheduleRepeating

public Stoppable scheduleRepeating(long time,
                                   Steppable event,
                                   long interval)
If the event is valid, and the current time is less than time, schedules the event to occur once every interval's worth of clock ticks starting at time, 0 ordering, and returns a Stoppable, else returns null. Returns a Stoppable which you can use to stop the repeated scheduling from occuring any more.

Note that calling stop() on the Stoppable will not only stop the repeating, but will also make the Schedule completely forget (lose the pointer to) the Steppable scheduled here. This is particularly useful if you need to make the Schedule NOT serialize certain Steppable objects. Do not use this with a real-valued schedule.


scheduleRepeating

public Stoppable scheduleRepeating(long time,
                                   int ordering,
                                   Steppable event)
If the event is valid, and the current time is less than time, schedules the event to occur once every clock tick starting at time, with the given ordering, and returns a Stoppable, else returns null. Returns a Stoppable which you can use to stop the repeated scheduling from occuring any more.

Note that calling stop() on the Stoppable will not only stop the repeating, but will also make the Schedule completely forget (lose the pointer to) the Steppable scheduled here. This is particularly useful if you need to make the Schedule NOT serialize certain Steppable objects. Do not use this with a real-valued schedule.


scheduleRepeating

public Stoppable scheduleRepeating(long time,
                                   int ordering,
                                   Steppable event,
                                   long interval)
If the event is valid, and the current time is less than time, schedules the event to occur once every interval's worth of clock ticks starting at time, with the given ordering, and returns a Stoppable, else returns null. Returns a Stoppable which you can use to stop the repeated scheduling from occuring any more.

Note that calling stop() on the Stoppable will not only stop the repeating, but will also make the Schedule completely forget (lose the pointer to) the Steppable scheduled here. This is particularly useful if you need to make the Schedule NOT serialize certain Steppable objects. Do not use this with a real-valued schedule.