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

Reply via email to