Code bloat! The functionality of this class could be implemented fairly

easily in java 1.5 by using a ThreadPoolExecutor with 1 thread in the
pool and a special queue implementation that merged like entries,
but we want this special functionality now.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@1538 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
samskivert@gmail.com
2004-12-06 21:58:00 +00:00
parent 19fc217b07
commit 51bcd06a15
@@ -0,0 +1,133 @@
//
// $Id$
package com.samskivert.util;
import java.util.ArrayList;
import com.samskivert.Log;
/**
* A simple serial executor, similar to what can be done in java 1.5, only
* using 1.4 and samskivert-style tasks. This is like RunQueue only slightly
* more sophisticated. Bloat!
*/
public class SerialExecutor
{
/**
* A task to run in serial on the executor.
*/
public static interface ExecutorTask
{
/**
* This will be called when one task is on the queue to be processed
* and another task is going to be added to the queue.
*
* @return true if the tasks were merged and the other task does not
* need to be added to the queue.
*/
public boolean merge (ExecutorTask other);
/**
* The portion of the task that will be executed on the executor's
* thread.
*/
public void executeTask ();
/**
* After the task has been executed, this will be called
* on the ResultReceiver thread to post-process the results of the
* task.
*/
public void resultReceived ();
}
/**
* Construct the SerialExecutor.
*/
public SerialExecutor (Invoker.ResultReceiver receiver)
{
_receiver = receiver;
}
/**
* Add a task to the executor, it is expected that this method is
* called on the ResultReceiver thread.
*/
public void addTask (ExecutorTask task)
{
for (int ii=0, nn=_queue.size(); ii < nn; ii++) {
ExecutorTask taskOnQueue = (ExecutorTask) _queue.get(ii);
if (taskOnQueue.merge(task)) {
return;
}
}
// otherwise, add it on
_queue.add(task);
// and perhaps start it going now
if (!_executingNow) {
checkNext();
}
}
/**
* Execute the next task, if applicable.
*/
protected void checkNext ()
{
_executingNow = !_queue.isEmpty();
if (_executingNow) {
ExecutorTask task = (ExecutorTask) _queue.remove(0);
ExecutorThread thread = new ExecutorThread(task);
thread.start();
}
}
/**
* The basic processing unit of the Executor.
*/
protected class ExecutorThread extends Thread
{
public ExecutorThread (ExecutorTask task)
{
_task = task;
}
// documentation inherited
public void run ()
{
try {
_task.executeTask();
} catch (Throwable t) {
Log.warning("ExecutorTask choked: " + t);
Log.logStackTrace(t);
}
_receiver.postUnit(new Runnable() {
public void run () {
try {
_task.resultReceived();
} catch (Throwable t) {
Log.warning("ExecutorTask choked: " + t);
Log.logStackTrace(t);
}
checkNext();
}
});
}
/** The task to execute. */
protected ExecutorTask _task;
}
/** The receiver to which we post a unit to process results. */
protected Invoker.ResultReceiver _receiver;
/** True if there is a thread currently executing a task. */
protected boolean _executingNow = false;
/** The queue of tasks to execute. */
protected ArrayList _queue = new ArrayList();
}