Async channels

Rémi Forax forax at univ-mlv.fr
Mon Apr 20 03:28:29 PDT 2009


Alan Bateman a écrit :
> Rémi Forax wrote:
>> Hi Alan, hi all,
>> I have some questions about channels and their implementations.
>> (I use the jdk7 workspace so sorry if it's already fixed).
>>
>> 1) Why 
>> SocketChannel.getRemoteAddress()/Async...Channel.getRemoteAddress()
>>    and Socket.getSocketRemoteAddress() doesn't have the same semantics ?
>>
>>   getSocketRemoteAddress() returns the remote address even
>>   if the connection is closed,
>>   getRemoteAddress() throws a IOException in that case.
> The getRemoteAddress method throws ClosedChannelException if invoked 
> on a closed channel. The reason for the IOException is to allow an 
> implementation retrieve the address only when required. 
> Socket#getSocketRemoteAddress, on the other hand, didn't originally 
> specify this case. There were a bunch of other "close socket" cases in 
> the java.net package that were also undefined. Early in jdk7 the 
> javadoc was updated to fix these up these cases; existing behavior had 
> to be specified to avoid breaking code that may have been relying on it.
As a server developer; I prefer the semantics of 
getSocketRemoteAddress() (as specified now)
to the one specified for getRemoteAddress().
At least half of the usages (and perhaps more) of getRemoteAddress() 
will be for logging purpose,
having the remote address persistent even if the channel is closed seems 
important to me,
for example, if you want to log that the channel is closed :)

[...]
>
>>
>> 3) The doc of AsynchronousChannel is not crystal clear for methods
>>     read() or write() that doesn't take a completion handler
>>     in case of IOException.
>>
>>     "In the first form, the methods defined by the {@link Future Future}
>>      interface may be used to check if the operation has completed, 
>> wait for its
>>      completion, and to retrieve the result."
>>
>>     Is future.get() will throw a ExecutionException that will wrap 
>> the corresponding
>>     IOException ?
> Yes, it will wrap the IOException (or maybe SecurityException in some 
> cases). I've made a note to myself to see if this can be made clearer.
See below ...
>
>>
>> 4) Why CompletionHandler.failed() take a Throwable and not a 
>> IOException ?
> It may be something other than IOException. The accept and receive 
> operations for example may fail with a SecurityException for example.
Argh,
I was hoping that SecurityException like any runtime exceptions is 
thrown synchronously.
I don't see why they have to be delayed.
As a  developer,  runtime exception means  you don't correctly 
understand the spec
so they have to be thrown sooner  than later  (if possible).
 
>
>>
>> 5) As specified in the doc of AsynchronousChannel about cancelation,
>>    "further attempts to initiate a {@code read} operation causes an
>>      unspecified runtime exception to be thrown".
>>   Why a runtime exception and not a call to the completion handler ?
> Yes, this bug can be caught before the I/O operation is initiated so 
> the IllegalStateException or other runtime exception can be thrown then.

I think I don't like the fact that runtime exceptions can be:
  1) thrown by read/write/accept/connect or
  2) catch by the completion handler
without be able to understand/predict why.

>
>>
>> 6) Is it possible to rename all Asynchronous* to Async*.
>>    I will *really* increase the readability of the types.
> This package doesn't use abbreviations in class names. Okay, the new 
> channels have longish class names but no big deal.
It's a big deal, if you take a look to the javadoc of the package (the 
bottom-left frame)
you only see a bunch of classes starting with Asynchronous* even if they 
are like selectors
reserved for advanced usages.
>
>>
>> 7) UnixAsynchronousSocketChannelImpl.onCancel() seems to have a 
>> copy&paste bug:
>>
>> public void onCancel(PendingFuture<?,?> task) {
>>        if (task.getContext() == OpType.CONNECT)
>>            killConnect();
>>        if (task.getContext() == OpType.READ)
>>            killConnect();    // <----------------------- killReading()
>>        if (task.getContext() == OpType.WRITE)
>>            killConnect();   // <----------------------- killWriting()
>>    }
> Thanks; amazingly this this bug doesn't have much impact.
Perhaps a test case is missing ?
>
>>
>>
>> 8) Why AsyncFileChannel.open(...) take an ExecutorService and not a 
>> AsyncChannelGroup ?
> File I/O is very different to socket I/O and it may not be feasible 
> for an implementation to share resources or thread pools between file 
> and network oriented channels. Think of an AsynchronousFileChannel as 
> a group of one containing one channel. The exception is when you use 
> the simpler open method as that will use the thread pool associated 
> with the default group.
Taking an Executor an not a AsyncChannelGroup doesn't prevent sharing.
Currently, you can write:

    ExecutorService executor=Executors.newCachedThreadPool();
    AsynchronousChannelGroup channelGroup = 
AsynchronousChannelGroup.withThreadPool(executor);
    AsynchronousServerSocketChannel serverSocketChannel = 
AsynchronousServerSocketChannel.open(channelGroup);
    AsynchronousFileChannel fileChannel = 
AsynchronousFileChannel.open(path, openOptions, executor);


Another questions, currently the linux code for asynchronous I/O is 
based on poll
like the selectors.
 - On linux, is it more inetrresting to use async calls or selectors 
beside the fact that
   code with async calls seem simplier to write (at least to me) ?
 - Is there a plan to use really async I/O on linux ?

>
> -Alan.
>
Rémi



More information about the nio-dev mailing list