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:
@@ -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();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user