Martin Desruisseaux wrote:
> It still not clear to we why the Process interface needs to be
> unrelated to standard Java API like Callable?
Hi Martin;
I have been having a hard time communicating this one. I think we are
both looking at the same code and seeing different things.
We have three designs in front of us...
1) Thread/Runnable
Thread and Runnable are a good base, but the design suffers from some
serious flaws with respect to canceling a running Thread.
There is one point of contact, the code that starts the thread needs to
end it etc...
Thread t = new Thread( Runnable );
t.start();
2) Future / Callable
This is an API produced "on top" of Thread and Runnable (literally on
top of it) that takes charge of the Thread canceling problem. There are
several examples built around this core (scheduled futures, swingworker
and so on...) but they do not add anything to this core.
In this design the Future is responsible for the Thread, and will take
care of kicking the Thread into life (adapting Callable to Runnable
internally) and carefully canceling the Thread. The Future has a
reference to the Thread (in order to carefully cancel) but very little else.
These facilities do not provide any kind of information or reporting on
the running Callable. The moment we provide more we have stepped outside
of what Future / Callable can do out of the box.
There is one point of contact; the Future holding on to the callable has
a chance to end it; and report the value when available.
Future later = Executor.submit( callable );
... other code....
Object value = later.get(); // this will block...
So what would this look like if we take the same approach?
Single point of contact:
Progress later = Executor.submit( callable );
... other code....
Object value = later.get(); // this will block...
Or two points of contact?
Future later = Executor.submit( callable, progress );
... other code....
Object value = later.get(); // this will block...
3) Process (as it stands)
Process here is trying to exist *just* as half of the design -
specifically because it will be hosted by Future/Callable or any other
number of process engines namely the part that is run. The focus here is
on communicating the parameters that are required; and what the results
look like. I know up front that Progress can be integrated well with
Future/Callable (and even Thread/Runnable). I also know that I need to
make it work in a range of situations from Eclipse Jobs, to YAWL or JBPM...
So my turn to ask ... what is the problem? I feel the problem is
ProgressListener; but you know how that is used to report sub process
information etc... and I have explained it to Eclesia.
> Why the following can't work?
> public interface Process extends Callable {
> void addListener(ProgressListener);
> void removeListener(ProgressListener);
> void cancel();
> }
To answer your question - it is not compatible with the
relationship/responsibilities between and Future/Callable. While it is a
fine approach; it goes against the design of the system.
Specifically the Future/Callable framework has the following
classes/responsibilities/collaboration:
- Executor - take responsibility for running Callable (or Callable
Extensions), provides facilities for polling and listing running
Callables (actually it lists the Futures)
- Callable - provided by programmers to capture a block of code they
want to have executed in another thread
- Future - callback object used by Executor to communicate with the
programmer; used to monitor and control the Callable
So if we follow this design and imitate it for Process/Progress:
- Executor2 - provide our own implementation that can handle Process and
Progress, additional facilities for listing Processes etc...
- Process - extends Callable
- Progress - extends Future with additional methods to report on progress
This approach limits the point of contact (for reporting progress) to
something under the control of the Executor; the *only* relationship
allowed with a Progress is through the Executor managing it; the
Executor can return a Future (so others can take part) - but what that
future does is still under the control of the Executor.
Please understand that this is way out of scope (we are now starting to
write our own ProcessEngine; something which GeoTools should stay far
away from)....
/** Based on ScheduledExecutorService example... */
ProcessExecutor extends Executor {
Progress process( Process process );
Progress process( Callable<V> callable ); // progress reported will
be pretty limited
}
Progress extends Future<Map<String,Object>> {
int getProgress(); // between 0 and 100, -1 busy
String getTask();
}
Process {
Map<String,Object> process( ProgressListener listener );
}
When you go to implement Process you will still end up with a
ProgressListener (because of the ability to report on sub progress). It
is still a single ProgressListener (provided by the Executor). On the
the other end what does the Progress do? Frankly I don't care that is up
to who ever wants to implement this ... you could have it broadcast
events to multiple listeners if you want. It does not effect the
definition of Process at all.
Jody
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Geotools-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel