why not both Future and CompletionHandler?
Wolfgang Baltes
wolfgang_baltes at hotmail.com
Thu Apr 14 10:53:36 PDT 2011
On 2011-04-14 10:37, Wolfgang Baltes wrote:
>
>
> On 2011-04-14 09:56, Rémi Forax wrote:
>> On 04/14/2011 06:21 PM, wolfgang.baltes wrote:
>>>
>>> On 2011-04-14 08:38, Alan Bateman wrote:
>>>
>>>
>>> Sangjin Lee wrote:
>>>
>>> Yes, I think it can come very handy if you want to add some
>>> cross-cutting concerns in the completion handlers but allow
>>> the end users to interact with the result via Future.
>>>
>>> For example, suppose I build a framework/library for others
>>> using the async channels (HTTP app, ssh app, etc.). I want
>>> to allow my users freedom to choose between the "pull"
>>> (future) and the "push" (completion handler). However,
>>> *regardless* of what my end user choose to interact with the
>>> result, I want to be able to inject some concerns like
>>> logging, instrumenting, etc. in the form of a completion
>>> handler (can be completely internal to the framework).
>>>
>>> With the current APIs, if the user wants a future, the
>>> framework cannot use the completion handler and I would need
>>> to find another way to inject such logic. Or if I want to
>>> retain the completion handler for the framework, then I
>>> would need to create my own future objects to provide to the
>>> end users. Either approach is doable, but it would be so
>>> much easier if the NIO.2 APIs provide both mechanisms in a
>>> single method call. My 2 cents. Thanks!
>>>
>>> For high performance applications using completion handlers then
>>> we don't want to future Future objects that won't be used. In
>>> your framework/library then won't it return your own Future type
>>> anyway?
>>>
>>> -Alan.
>>>
>>> (This is a resend with subject filled in. Sorry, but I have email
>>> problems this morning.)
>>> Hi,
>>>
>>> I encountered a similar need. The problem I wanted to solve was that
>>> I didn't want to have my main code thread wait (or block) for
>>> completion of the I/O operation only to start a follow up task. I
>>> created a class
>>>
>>> class CompletionFuture
>>> extends FutureTask<V>
>>> implements CompletionHandler<Integer, A>
>>>
>>> that does the trick. It's constructor takes a Callable<V> as
>>> argument. The created object is a Future<V>. The CompletionFuture's
>>> (or CompletionHandler's) completed(Integer, A) method essentially
>>> submits itself (in its role as FutureTask) to an ExecutionService.
>>> When this task is finished the get() method unblocks. The
>>> CompletionFuture's failed(Integer, A) method shortcuts the task by
>>> calling the setException(Throwable) method. Again, this unblocks
>>> get(), by throwing the exception. Alternatively, fail could also run
>>> the task using some instance field to indicate the failed condition.
>>>
>>> I can send a skeletal version of my code if desired. I am not sure
>>> that this functionality is sufficiently generic to be of general
>>> interest as it may need to be adopted to every specific application.
>>> For example, the task could be executed by the same thread as the
>>> CompletionHandler, by an ExecutionService other than the main
>>> thread, or the thread pool in which the main thread runs.
>>>
>>> Wolfgang.
>>
>> How do you implement cancel ?
>>
>> Rémi
>>
> Rémi,
>
> I don't/can't cancel the I/O operation, but I can the following task.
> So far I used this only for file I/O operations, and didn't see the
> need for cancellation. Again, I don't want to say that my solution is
> of too board an appeal, but it may fit certain needs.
>
> Wolfgang.
Rémi,
As an addition to my previous reply: I didn't find clear semantics on
how to cancel an I/O operation; that is, I couldn't find a clear
explanation of what cancel() on a Future returned by an I/O operation
would actually do. Alan's memo seems to indicate that it may not do much.
On the other side, the CompletionFuture I described allows cancellation
of the task (i.e., the argument to the constructor).
Wolfgang.
More information about the nio-dev
mailing list