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