On Thu, Aug 7, 2008 at 6:57 PM, Dain Sundstrom <[EMAIL PROTECTED]> wrote:
> My real goal is I would like to write client code that can efficiently
> manage large sets results from async methods, or long running async mehtods.
>  Currently the only way to get a result for a anync method is to block
> (Future.get()) or to poll (Future.get(long timeout, TimeUnit units), both of
> which eat up a precious thread resources (or on an IBM mainframe computation
> resources).

Well, in a polling solution you would probably first check if the
future is done (Future.isDone()) and then call Future.get() to get the
result. In such case, Future.get() would return immediately.

> What I'd like to see an interface like this in EJB or as a second maybe the
> EE concurrent spec:
>
>    public interface ManagedFuture<T> extends Future<T> {
>        void onComplete(Runnable runnable);
>        void onComplete(Runnable runnable, ExecutorService executorService);
>    }
>
> The is would allow me to write client code that is notified when the async
> result is ready.  This interface could even be an optional interface the
> server could return, and I could simply wrap it as follows:
>
>    public class FakeManagedFuture<T> implements ManagedFuture<T> {
>        private final Future<T> future;
>
>        public FakeManagedFuture(Future<T> future) {
>            this.future = future;
>        }
>
>        public boolean cancel(boolean mayInterruptIfRunning) {
>            return future.cancel(mayInterruptIfRunning);
>        }
>
>        public boolean isCancelled() {
>            return future.isCancelled();
>        }
>
>        public boolean isDone() {
>            return future.isDone();
>        }
>
>        public T get() throws InterruptedException, ExecutionException {
>            return future.get();
>        }
>
>        public T get(long timeout, TimeUnit unit) throws
> InterruptedException, ExecutionException, TimeoutException {
>            return future.get(timeout, unit);
>        }
>
>        public void onComplete(Runnable runnable) {
>            onComplete(runnable, getDefaultExecutorService());
>        }
>
>        public void onComplete(final Runnable runnable, ExecutorService
> executorService) {
>            if (future instanceof ManagedFuture) {
>                ManagedFuture managedFuture = (ManagedFuture) future;
>                managedFuture.onComplete(runnable);
>            } else {
>                executorService.submit(new Runnable() {
>                    public void run() {
>                        try {
>                            future.get();
>                        } catch (Exception ignored) {
>                        }
>                        runnable.run();
>                    }
>                });
>            }
>        }
>
>        private ExecutorService getDefaultExecutorService() {
>            return null;
>        }
>    }
>
> Alternatively, the spec could define a CompletionService (injectable or via
> JNDI) link this:
>
>    public interface CompletionService {
>        void onComplete(Future future, Runnable runnable);
>        void onComplete(Future future, Runnable runnable, ExecutorService
> executorService);
>    }
>

I don't think I fully understand you, so let me describe my
understanding of things:

You can be notified when the result is ready using the
ManagedTaskListener for example:

executor.submit( <task>, new ManagedTaskListener() {
           public void taskDone(Future f, ManagedExecutorService e) {
                   Object result = f.get(); // returns immediately
                   // do your work here
           }
           ...
});

In general, with this method, the task would be some piece of code you
want to execute asynchronously in a separate thread.

But if your task itself is an asynchronous task, for example:

  foo.invokeAsynch(params, new AsynchResult() {
                public void complete(Object result) {
                   // called when asynch method completes
                }
  });

There is no point of converting that into a blocking task and
submitting it to an executor (since it will just effectively waste a
thread):

new Callable() {
  public void call() {
    AsynchResult result = new AsynchResult();
    foo.invokeAsynch(params, result);
    result.waitFor(); // blocks until result.completed() is called
 }

So you want an executor to recognize somehow these special asynch
tasks and handle them appropriately (i.e. without assigning a
dedicated thread). Is that right? If so, why not define AsynchTask
interface (or something like that), e.g.:

AsynchTask {
  start(AsynchResult h);
}

or (so that can be put on existing Runnable or Callable tasks)

AynchTask {
  setAsynchResult(AsynchResult h);
}

With this the executor could recognize an asych task and just call
start() or run() or call() method (on the same or another thread) to
start the asynch task and create a special Future implementation that
would use the AsynchResult to get the result.

Is that what you are thinking or am I off in the weeds somewhere?

Jarek

> For servers that don't implement async client notifications, they could
> simply poll or block under the covers.
>
> Regardless, I think we should provide something like this in OpenEJB, but
> I'd like to be able to write apps that are both efficient and portable.
>
> -dain
>
> On Aug 7, 2008, at 1:23 PM, Jarek Gawor wrote:
>
>> On Wed, Aug 6, 2008 at 1:43 PM, Dain Sundstrom <[EMAIL PROTECTED]> wrote:
>>>
>>> On Aug 6, 2008, at 10:14 AM, Jarek Gawor wrote:
>>>
>>>> On Wed, Aug 6, 2008 at 1:00 PM, Dain Sundstrom <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>> On Aug 5, 2008, at 1:25 PM, David Jencks wrote:
>>>>>
>>>>>> Is there something similar in the ee concurrency spec?
>>>>>
>>>>> Never heard of that spec.  Do you have any details?
>>>>
>>>> Here's some info on the spec:
>>>>
>>>> http://gee.cs.oswego.edu/dl/concurrencyee-interest/index.html
>>>>
>>>> http://www.jcp.org/en/jsr/detail?id=236
>>>>
>>>> and in Geronimo (trunk) we have a basic implementation of the draft
>>>> spec.
>>>
>>> Interesting.  It would be nice if there were something like this for the
>>> client side.  One big I issue I see with EJB async methods is there is no
>>> way to be notified when the result of an async method is ready.  This API
>>> is
>>> very close to being what we would need.  Specifically this method on
>>> ManagedExecutorService:
>>>
>>>      submit(Callable<T> task, ManagedTaskListener taskListener)
>>>
>>> which adds a task to run with a listener for it's completion.  For async
>>> result support we would need something like this:
>>>
>>>      waitForResult(Future<?> future, ManagedTaskListener taskListener)
>>
>> There is ManagedExecutorService.invokeAll(Collection<Callable> tasks,
>> ManagedTaskListener listener) function which effectively does two
>> things: 1) it submits the tasks and 2) waits until they all finish.
>> Pretty much the same as ExecutorService.invokeAll() except the
>> listener which you could use to figure out which task completed so
>> far.
>>
>>> of maybe
>>>
>>>      submit(new WaitForCallable(myFuture), taskListener)
>>>
>>> If the future instance implemented a special "notifiable" interface, the
>>> Executor service would simply add the listener to the future.  If it
>>> didn't
>>> implement that interface, it would use a thread to block (or periodically
>>> poll) for the result.
>>
>> I don't know the OpenEJB code very well, but what if it returned a
>> Callable object instead of a Future. That way, I think, it would fit
>> nicely with either ExecutorService or ManagedExecutorService. And as
>> you mentioned, you could always wrap a Future into a Callable or
>> Runnable.
>
> That is an interesting idea.  If an async method could optionally return
> Callable<T> instead of Future<T>, the callable could be the special
> "notifiable" interface I talk about above.  Assuming the Callable returned
> and the ManagedExecutorService are supplied by the same vendor, the
> ManagedExecutorService could detect the callable is for ansync result and
> wait for results without assigning a thread
>
> Unfortunately, it would mean that the coder of the aync method would need to
> decide if the caller wanted a Future or a Callable which kind of stinks.
>
>
>
>
>>> Something like this would allow users to write efficient and spec
>>> compliant
>>> async clients.
>>>
>>> David (Jencks), are you working on this spec?  Any chances on getting
>>> something like this in?
>>
>> I'm working on the spec and the implementation in Geronimo and just
>> joined the Expert Group so if you have any comments or specific
>> proposals please let me know.
>>
>> Jarek
>
>

Reply via email to