Class Scheduler

java.lang.Object
gnu.cajo.utils.extra.Scheduler
All Implemented Interfaces:
Serializable

public final class Scheduler extends Object implements Serializable
This class is for scheduling the non-preemptive execution of tasks. The class creates a single thread, and will independently manange and run its loaded objects. The Scheduler accepts objects for scheduling, at any time during its existence. The scheduled object must implement no-arg, void slice() method, to be used as a time slice, in which to perform some fixed piece of functionality. The scheduler will provide the calling mechanism. An objectwith this type of method implementation will be considered a task for the purposes of this class.

The scheduler's purpose is to provide an exclusive thread of execution amongst the scheduled tasks. It will assure that only one of the tasks is running at any given time, therefore shared memory between the tasks cannot be corrupted by the scheduler due to synchronization problems.

All scheduler methods are properly synchronized, to allow task loading, unloading, and management, from other threads, as well as by the scheduled tasks themselves.

Up to 32 tasks can be loaded, at any given time, for scheduling. Once loaded, tasks can be scheduled to run in any, or all, of three ways; Synchronous, Triggered, or Asynchronous. The class implements three methods to flag a loaded task as such. The following is a description of the scheduling algorithm:

When a task is flagged as asynchronous, it will be run only when no tasks are flagged as synchronous, or triggered, at the start of its slice. Its asynchronous flag is not cleared when it is run, meaning until stopped, it will be run again automatically, as scheduling permits. Scheduling among multiple asynchronous flags is round-robbin, to ensure each an opportunity to run. This provides a method for scheduling low-priority tasks. Typically an asynchronous task will break its functionality into distinct pieces, and use a switch() type mechanism to execute only one piece per timeslice.

When a task is flagged as triggered, will run before any tasks flagged asynchronous, but only when no tasks are flagged as synchronous, at the start of its slice. The trigger flag is cleared when the task is run, meaning that unless re-flagged as triggered, it will not run again through the trigger scheduling algorithm. This provides an event-driven mode of execution, but at a lower priority than the synchronous mode.

When a task is flagged as synchronous, it will run before any triggered, or asynchronous flagged tasks are allowed to run. Its synchronous flag is also cleared when the task is run. Since the scheduling is not preemptive, any currently running task is allowed to complete. This flag provides the highest responsiveness to a synchronizing event.

The stop method is used to prevent the execution of any flagged task. General notes:

  • Since scheduling is not preemptive, developers must agressively minimize asynchronous task's run time length, to decrease the latency of event responsiveness. This becomes especially important when tasks are elevated in priority.
  • Non-preemptive scheduling eliminates all synchronization concerns for objects shared between scheduled tasks.
  • As a general rule: try to use asynchronous scheduling initially. Then, as the design runtime load increases, selected tasks can be boosted in proiority to achieve the desired responsiveness.

Note: This class supports serialisation. It will restart the scheduling task automatically on deserialisation. However, in order for serialisation to succeed, all of the loaded tasks must also be serialisable.

Version:
1.0, 01-Nov-99 Initial release
See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private static final String
     
    private final Runnable
     
    private Object[]
     
    private int
     
    private int
     
    private Thread
     
    private int
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    Nothing is performed in the constructor, since no tasks can be scheduled for execution until they have been loaded.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    drop(int task)
    This method clears all scheduling flags for the indicated task, and also removes it from the table.
    int
    load(Object task)
    This method accepts a task to be scheduled.
    boolean
    The purpose of this function is to reduce event-driven task latency by allowing asynchronous tasks to voluntarily exit prematurely.
    private void
     
    boolean
    setEnabled(boolean enabled)
    This method will start, or suspend, the scheduler.
    boolean
    soon(int task)
    This method sets the triggered execution flag for a task.
    void
    stop(int task)
    This method clears all scheduling flags for indicated task.
    boolean
    sync(int task)
    This method sets the synchronous execution flag for a task.
    boolean
    wake(int task)
    This method sets the asynchronous execution flag for a task.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • INDEX_INVALID

      private static final String INDEX_INVALID
      See Also:
    • thread

      private transient Thread thread
    • syncFlags

      private int syncFlags
    • soonFlags

      private int soonFlags
    • wakeFlags

      private int wakeFlags
    • list

      private Object[] list
    • kernel

      private final Runnable kernel
  • Constructor Details

    • Scheduler

      public Scheduler()
      Nothing is performed in the constructor, since no tasks can be scheduled for execution until they have been loaded.
  • Method Details

    • readObject

      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
      Throws:
      IOException
      ClassNotFoundException
    • setEnabled

      public boolean setEnabled(boolean enabled)
      This method will start, or suspend, the scheduler. The scheduler will be started automatically when the first task is flagged for execution. The method is idempotent; therefore enabling an already enabled scheduler will cause no effect, just as disabling a currently disabled scheduler.
      Parameters:
      enabled - The flag to indicate if this is a startup, or suspend operation.
      Returns:
      true if successfully started or stopped, false if not for logical reasons, i.e. already stopped/started, no tasks running.
    • load

      public int load(Object task)
      This method accepts a task to be scheduled. If the task is accepted, it is placed in the table, but will not be executed, until it is flagged for operation. If the execution of the task slice results in an exception, the task will be automatically dropped from the queue.
      Parameters:
      task - The task to attempt to schedule, it may be either local, remote, or even a proxy, when enabled.
      Returns:
      the index of the task in the table. The task table index is used in the scheduling methods.
      Throws:
      IllegalArgumentException - If the task table is full.
    • sync

      public boolean sync(int task)
      This method sets the synchronous execution flag for a task. The flag will be cleared automatically, when the scheduler calls this task.
      Parameters:
      task - The index of the task in the table
      Returns:
      false if the task was already flagged, or not in the queue, else true if successfully flagged.
      Throws:
      IllegalArgumentException - If the task table index is invalid.
    • soon

      public boolean soon(int task)
      This method sets the triggered execution flag for a task. It will be cleared just before passing execution on to the task.
      Parameters:
      task - The index of the task in the table
      Returns:
      true if successfully flagged, false if already flagged
      Throws:
      IllegalArgumentException - If the task table index is invalid.
    • wake

      public boolean wake(int task)
      This method sets the asynchronous execution flag for a task. It will not be cleared when passing execution on to the task. The flag will retain its state, until disabled through the stop method.
      Parameters:
      task - The index of the task to be scheduled for continuous asynchronous execution.
      Returns:
      true if successfully flagged, false if already flagged.
      Throws:
      IllegalArgumentException - If the task table index is invalid.
    • stop

      public void stop(int task)
      This method clears all scheduling flags for indicated task. The task will reamain in the table however. Note: to remove a task, use the drop method instead, it automatically calls stop, before removing the task from the table.
      Parameters:
      task - The index of the task in the table
      Throws:
      IllegalArgumentException - If the task table index is invalid.
    • drop

      public void drop(int task)
      This method clears all scheduling flags for the indicated task, and also removes it from the table.
      Parameters:
      task - The index of the task to stop and remove from the table.
      Throws:
      IllegalArgumentException - If the task table index is invalid.
    • pending

      public boolean pending()
      The purpose of this function is to reduce event-driven task latency by allowing asynchronous tasks to voluntarily exit prematurely. To improve responsiveness, asynchronous tasks could check this method, before going on to another functionally distinct section of its task execution. It is normally checked when the async task has some periodic extra work, if the method returns false, the extra work could be processed in its current slice.
      Returns:
      true if synchronous or triggered tasks have been flagged for execution, false if it is OK for the task to continue running a little longer.