Class Scheduler
- java.lang.Object
-
- gnu.cajo.utils.extra.Scheduler
-
- All Implemented Interfaces:
java.io.Serializable
public final class Scheduler extends java.lang.Object implements java.io.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:
- Serialized Form
-
-
Constructor Summary
Constructors Constructor Description Scheduler()
Nothing is performed in the constructor, since no tasks can be scheduled for execution until they have been loaded.
-
Method Summary
All Methods Instance Methods Concrete Methods 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(java.lang.Object task)
This method accepts a task to be scheduled.boolean
pending()
The purpose of this function is to reduce event-driven task latency by allowing asynchronous tasks to voluntarily exit prematurely.private void
readObject(java.io.ObjectInputStream in)
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.
-
-
-
Field Detail
-
INDEX_INVALID
private static final java.lang.String INDEX_INVALID
- See Also:
- Constant Field Values
-
thread
private transient java.lang.Thread thread
-
syncFlags
private int syncFlags
-
soonFlags
private int soonFlags
-
wakeFlags
private int wakeFlags
-
list
private java.lang.Object[] list
-
kernel
private final java.lang.Runnable kernel
-
-
Method Detail
-
readObject
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException
- Throws:
java.io.IOException
java.lang.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(java.lang.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:
java.lang.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:
java.lang.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:
java.lang.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:
java.lang.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:
java.lang.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:
java.lang.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.
-
-