AsynchronousByteCharChannel and Timeouts

Alan Bateman Alan.Bateman at oracle.com
Tue Jul 13 10:46:08 PDT 2010


cowwoc wrote:
> :
> The Context
> ------------
>
> I'm trying to implement AsynchronousByteCharChannel in an
> implementation-independent manner so that you can feed in any
> AsynchronousByteChannel. Now, in light of the fact that
> AsynchronousByteChannel does not talk about timeouts, nor can
> AsynchronousByteCharChannel. Eventually, though, my application needs to be
> able to read-with-timeout from an underlying serial port. This forces me to
> implement read-with-timeout on top of an interface that only provides
> read-forever.
>
> AsynchronousSocketChannel's Javadoc reads "A timeout may leave the channel,
> or the underlying connection, in an inconsistent state. Where the
> implementation cannot guarantee that bytes have not been read from the
> channel then it puts the channel into an implementation specific error
> state." but for serial ports, a timeout does *not* leave them in an
> inconsistent state so the question becomes: how can I continue using the
> channel after a timeout?
>
> I am arguing that although the specification says that a timeout *may*
> result in an inconsistent state, it makes it impractical to do otherwise.
>   
Do you have  a suggestion for how it could specified otherwise? 
Cancellation (be it by timeout, or invoking the Future's cancel method) 
is an awkward topic. We can't assume that the underlying I/O operation 
can be cancelled cleanly as it is highly operating system/implementation 
specific.

In the case of a stream connection (AsynchronouSocketChannel), if 
cancellation creates the potential for data loss then the channel is 
useless as applications assume a reliable stream. The only practical 
thing you can do is close the channel (which is what usually happens 
anyway when the peer doesn't respond without a certain time). If you 
implement it in such a way that the channel remains in a consistent 
state then you can continue to use it.

> Specific Problems
> -----------------
>
> Say I want to implement read-with-timeout on top of a read-forever
> implementation. A user invokes:
> readWithTimeout(n=10) followed by
> readWithTimeout(n=5)
>
> Given a AsynchronousByteChannel that initially has 9 bytes buffered. When
> the user invokes readWithTimeout(n=10) the specification does not guarantee
> that read() will return 9 bytes without blocking. Because I cannot safely
> assume the implementation must return immediately once it receives at least
> one byte I must invoke AsynchronousByteChannel.read(n=1). Consider what
> would happen if I did not: If I issued AsynchronousByteChannel.read(n=10)
> and the call blocked indefinitely, the first user call would result in a
> timeout. The user would then issue readWithTimeout(n=5). Now, technically
> speaking the underlying AsynchronousByteChannel has sufficient bytes to
> return right away, but practically speaking it is blocked trying to read 10
> bytes so I end up blocked for no reason.
>
> So point #1: Perhaps the specification should require implementations to
> return immediately if it can return at least one byte.
>   
In this example the first read should complete immediately having read 9 
bytes. Maybe we need to make this clearer in the spec, but in summary, 
if you initiate a read with a buffer that has r bytes remaining in the 
buffer, then read will complete having read up to r bytes. There should 
be no expectation that the read doesn't complete until r bytes have been 
read.

Also just to clarify one thing - the read (and write) methods in this 
API are non-blocking (just mentioning this as your talk about blocking 
indefinitely).

>
> My second argument is that we would be better off if AsynchronousByteChannel
> only contained read-with-timeout methods as opposed to placing read-forever
> in AsynchronousByteChannel and adding read-with-timeout in
> AsynchronousSocketChannel. I argue that it's always easier and more
> efficient to implement read-forever on top of read-with-timeout than the
> opposite. I think the fact that we only have one kind of
> AsynchronousByteChannel subclass (for sockets) prevents us from properly
> validating that the design makes sense for different kinds of devices.
>   
There may be merit in this although it increases the burden on the 
implementor and the only channel in this API that could implement it is 
AsynchronouSocketChannel.

-Alan.


More information about the nio-discuss mailing list