jcontrol.lang
Class Deadline

java.lang.Object
  extended by jcontrol.lang.Deadline

public class Deadline
extends Object

JControl deadline.

In embedded control there is often the need for realtime tasks. Some tasks are perodically repeating and some are sporadical but in both cases the calculation has to be finished in a specified period of time (time constraint).

The JControl virtual machine is beside the normal priority driven multithreading scheme able to assign deadlines to sequences of code. Then the scheduler is switched to EDF (earliest deadline first) mode. So a thread is privileged as long it has the most pressing deadline compared to other threads (and threads without deadline).

JControl deadlines depend on thread synchronisation. To enter a deadline you have to enter a monitor (a synchronized block) on the deadline object. So the same mechanism used for thread synchronization is used for deadline consistency. For the same reason you can't use the same deadline object on different threads at the same time.

Realtime tasks have different demands, all these demands are covered with the JControl deadline concept, some examples explain these.


Sporadic tasks

If some realtime task does not specify a specific trigger but a specific time period to process, you could simply synchronize on a new deadline object specifying a specific time constraint (25ms in this case):
 synchronized(new Deadline(25)) {
   [...] // your code that has to be processed in 25ms
 }
 
the deadline is entered in the moment of entering the monitor, not at object creation time. At the moment of leaving the monitor, the deadline is checked and a wait is forced for the remaining time. If your code took too much time to process, your application is able to check this at runtime:
 Deadline d=new Deadline(25);
 synchronized(d) {
   [...] // your code that has to be processed in 25ms
   try{
     d.check();
   } catch(DeadlineMissException e) {
     [...] // emergency code sequence
   }
 }
 
The check() command behaves like Object.wait() as a IllegalMonitorStateException is thrown if your thread is not the owner of the monitor of the deadline object (if not invoked from within a synchronized block). You can also put the try-catch outside the synchronized block in this case the catch sequence is processed in normal priority scheduling mode.

You can recycle the deadline object after using in this or in another thread, in both cases the deadline is set to the new point of time at the moment entering the monitor. Another way of entering a deadline is overriding the Deadline class and create some synchronized methods, e.g. an anonymous class:

 new Deadline(25) {
   public synchronized void critical(){
     [...] // your code that has to be processed in 25ms
   }
 }.critical();
 


Periodic tasks

If your realtime task has to be executed in equidistant time steps, you can easily append another time period to your current valid deadline.
 Deadline d=new Deadline(25);
 try{
   synchronized(d) {
     for(;;) {
       [...] // your code that has to be processed in 25ms
       d.append(25);
     }
   }
 } catch(DeadlineMissException e) {
   [...] // emergency code sequence
 }
 
So append() behaves like check() and leaving and entering the synchronized block combined: the DeadlineMissException could be thrown if the deadline was missed or the current thread is forced waiting until the old deadline is reached. But there is one difference: the new deadline is immediately appended to the old one, so no time is lost (which would happen if you first leave the EDF scheduled block and then enter it again).

It's not required to append equidistant deadlines, it is also possible to determine the times at runtime:

 Deadline d=new Deadline(1);
 synchronized(d) {
   for(int x=2;x<=25;x++) {
     [...] // your code that has to be processed in x-1 ms
     try{
       d.append(x);
     catch(DeadlineMissException e) {
       [...] // emergency code sequence
     }
   }
 } 
 
In this example the deadlines are varying from 1 to 25, note that the fist time constraint is defined at the Deadline constructor and all others by the append command. Here the catch is inside the loop so if a deadline is missed (more likely in the beginning) the emergency code sequence is processed but the new deadline is still appended to the (already missed) old one. So even if the one or the other deadline was missed it is possible to catch up the sequence with longer constraints later.


Aperiodic tasks

Sometimes tasks are triggered by external events (input, buffer etc.). The well known wait-notify scheme also works with deadlines. If you do a wait() on the deadline object, the monitor and the deadline are left. If the thread continues execution triggered by a notify or another thread a new deadline is entered immediately:
 Deadline d=new Deadline(25);
 try{
   synchronized(d) {
     for(;;) {
       d.wait(); // tempoary leaving the deadline (and EDF privileges)
       [...]     // your code that has to be processed in 25ms
     }
   }
 } catch(DeadlineMissException e) {
   [...] // emergency code sequence
 }
 


Nesting tasks

It is possible to nest deadlines but this works not for the same deadline object as a synchronized within a synchronized has no effect (no monitor is entered). It is possible to synchronize to another deadline object then the current deadline is memorized and overwritten by the new one (it doesn't make any difference if the new timeconstraint will result in a more or less pressing deadline than the current). After leaving the inner synchronized block the old deadline is restored. This works also if the inner synchronized block is within another class, e.g. if an API method uses deadlines for its implementation, this doesn't affect the application behaviour (assumed that the inner deadline is earlier than the outer).
 synchronized(new Deadline(25)) {
   synchronized(new Deadline(10)){
     [...] // your code that has to be processed in 10ms
   }
   [...] // your code that has to be processed in 25ms
         // (combined with the 10 above)
 }
 


Constructor Summary
Deadline(int timeconstraint)
          Constructs a new JControl deadline.
 
Method Summary
 void append(int newTimeconstraint)
          Appends a new timeconstraint to the currently valid deadline.
 void check()
          Just checks if the current deadline has run out.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, notifyAll, toString, wait
 

Constructor Detail

Deadline

public Deadline(int timeconstraint)
Constructs a new JControl deadline.

Parameters:
useTimeconstraint - the timeconstraint in milliseconds to generate the deadline from at the time of synchronization
Method Detail

append

public void append(int newTimeconstraint)
            throws IllegalMonitorStateException,
                   DeadlineMissException
Appends a new timeconstraint to the currently valid deadline. If nessesary the current Thread sleeps until the old deadline is reached.

Parameters:
newTimeconstraint - the timeconstraint to generate the new deadline from the end of the old deadline
Throws:
IllegalMonitorStateException - if the current thread isn't locked to this deadline
DeadlineMissException - of the old deadline has run out

check

public void check()
           throws IllegalMonitorStateException,
                  DeadlineMissException
Just checks if the current deadline has run out. This should be the last statement in the synchronized block.

Throws:
IllegalMonitorStateException - if the current thread isn't locked to this deadline
DeadlineMissException - of the old deadline has run out