Timber allows explicit expression of time constraints on reactions in a program. As a basis for this, we assume a notion of absolute or real time, which progresses independently of program executions. With each action call in a program is associated two absolute time instants, the baseline and the deadline. The intuition is that execution of the action must not start before the baseline and must be finished by the deadline. The time interval between these two instants is the time window of the action.
Timber programs cannot express or access absolute time, but the runtime system has access to a realtime clock and can obtain the current time.The resolution of this clock is platform-dependent.
There is, instead, a primitive type Time of durations, or lengths of time intervals, that may occur in programs. Time values can also be computed by the runtime system as the duration of the time interval between two instants.
The type is abstract; Time values can be constructed using the primitive functions
sec, millisec, microsec :: Int -> Time
which expect a non-negative argument. Of course, e.g., sec 1 and millisec 1000 denote the same time value.
There is a predefined instance numTime :: Num Time, so time durations can be added and subtracted using arithmetic notation, as in sec 2 + millisec 500. Subtraction of a larger value from a smaller yields time 0 and multiplication is undefined (an attempt to multiply two time values raises an exception).
To deconstruct time values, one uses the primitive functions
secOf, microsecOf :: Time -> Int
secOf rounds downwards to whole seconds and microsecOf returns the fraction, a value between 0 and 999999.
Time windows of reactions are assigned as follows:
In particular, the start action of a program gets as baseline the time instant when program execution begins.
When a message without time constraints is sent (i.e., an plain action is called) from a method with current baseline bl and deadline dl, the reaction to the message inherits both bl and dl.
The rule in the previous item can be changed by explicit program constructs:
The expression after t act sets the effective baseline for act to the current baseline plus t.
The expression before t act sets the effective deadline for act to its effective baseline plus t.
Special case: if the baseline denoted by an after construct is an already passed time instant, the effective baseline of the reaction is rounded off to the actual time of the call.
As mentioned above, programs cannot access absolute time, but they can measure durations of time intervals. For this, they make use of the primitive class timer, where
timer :: Class Timer struct Timer where reset :: Request () sample :: Request Time
When a new object of class timer is created, it stores the baseline of the current reaction. When, later, sample is called, the duration from the stored time to the current baseline is returned. Calls to reset updates the stored time to the current baseline.
Baselines and deadlines provide the basis for scheduling of Timber programs. The scheduler is preemptive and uses the EDF strategy (Earliest Deadline First):
At each interrupt (from external sources or internal runtime system timers) or method termination, the reaction to execute next is chosen as follows: Messages with future baselines cannot yet execute and are stored in a list sorted by baseline with a running timer that expires at the earliest baseline. Eligible messages are sorted by deadline and the message with the earliest deadline is chosen for execution.