Created services to facilitate doing things asynchronously in swing

applications.


git-svn-id: https://samskivert.googlecode.com/svn/trunk@22 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2000-12-06 03:25:19 +00:00
parent 16618d72e5
commit 0b9e558b4d
4 changed files with 175 additions and 0 deletions
@@ -0,0 +1,11 @@
#
# $Id: Makefile,v 1.1 2000/12/06 03:25:19 mdb Exp $
ROOT = ../../../..
SRCS = \
Task.java \
TaskMaster.java \
TaskObserver.java \
include $(ROOT)/build/Makefile.java
@@ -0,0 +1,33 @@
//
// $Id: Task.java,v 1.1 2000/12/06 03:25:19 mdb Exp $
package com.samskivert.swing.util;
/**
* A swing application requests that a task be invoked by the task
* master. The task master invokes the task on a separate thread and
* informs the swing application when the task has completed via the task
* observer interface. It does so in a way that plays nicely with the
* swing event dispatch thread (the swing application is notified of the
* task's completion on the event dispatch thread so that it can wiggle
* its user interface elements to its heart's desire).
*/
public interface Task
{
/**
* This method is called by the task master to invoke the task. The
* task should run to completion and return some value.
*/
public Object invoke ();
/**
* This method is called by the task master when it has received a
* request to cancel this task. If the task can be cancelled, abort
* should return true and the currently running call to
* <code>invoke()</code> should immediately return (the return value
* will be ignored). If the task cannot be cancelled, abort should
* return false and the task master will simply abandon the task and
* the thread on which it is running.
*/
public boolean abort ();
}
@@ -0,0 +1,98 @@
//
// $Id: TaskMaster.java,v 1.1 2000/12/06 03:25:19 mdb Exp $
package com.samskivert.swing.util;
import java.util.Hashtable;
import com.samskivert.util.Log;
/**
* The task master provides the ability for swing applications to invoke
* tasks on another thread and to conveniently receive the results of
* those tasks back on the swing event dispatch thread where the swing
* application can safely manipulate its user interface in response to the
* results of the task.
*
* <p/> Each task is run in it's own thread. Tasks are assumed to be
* infrequently run and expensive, so the overhead of creating a new
* thread to run each task is considered acceptable. If the need arises,
* the task master can be extended to support more sophisticated thread
* pooling but we'll cross that bridge when we come to it.
*/
public class TaskMaster
{
/** The log object to be used by the task master and services. */
public static Log log = new Log("com.samskivert.swing.util.task");
/**
* Instructs the task master to run the supplied task. The task is
* given the supplied name and can be referenced by that name in
* subsequent dealings with the task master. The supplied observer (if
* non-null) will be notified when the task has completed.
*/
public static void invokeTask (String name, Task task,
TaskObserver observer)
{
// create a task runner and stick it in our task table
TaskRunner runner = new TaskRunner(name, task, observer);
_tasks.put(name, runner);
// then start the runner up
runner.start();
}
/**
* Called by the task runner to remove itself from the task table when
* the task has completed or been aborted.
*/
protected static void removeTask (String name)
{
_tasks.remove(name);
}
protected static class TaskRunner extends Thread
{
public TaskRunner (String name, Task task, TaskObserver observer)
{
_name = name;
_task = task;
_observer = observer;
}
public void run ()
{
try {
Object result = _task.invoke();
if (_observer != null) {
try {
_observer.taskCompleted(_name, result);
} catch (Throwable t) {
log.warning("Observer choked in " +
"taskCompleted(): " + t);
}
}
} catch (Throwable t) {
if (_observer != null) {
try {
_observer.taskFailed(_name, t);
} catch (Throwable ot) {
log.warning("Observer choked in taskFailed(): " + ot);
}
}
}
TaskMaster.removeTask(_name);
}
public void abort ()
{
log.warning("abort() not currently supported.");
}
protected String _name;
protected Task _task;
protected TaskObserver _observer;
}
protected static Hashtable _tasks = new Hashtable();
}
@@ -0,0 +1,33 @@
//
// $Id: TaskObserver.java,v 1.1 2000/12/06 03:25:19 mdb Exp $
package com.samskivert.swing.util;
/**
* The task observer interface provides the means by which the task master
* can communicate the success or failure of a task invocation back to the
* originator of a task.
*/
public interface TaskObserver
{
/**
* If the task successfully runs to completion and returns a result,
* this member function will be called on the supplied observer.
*
* @param name The name under which the task was originally invoked.
* @param result The result returned by the task's
* <code>invoke()</code> method.
*/
public void taskCompleted (String name, Object result);
/**
* If the task fails to run to completion and instead throws an
* exception, this member function will be called on the supplied
* observer.
*
* @param name The name under which the task was originally invoked.
* @param exception The exception thrown by the task during the call
* to <code>invoke()</code>.
*/
public void taskFailed (String name, Throwable exception);
}