8198562: (ch) Separate blocking and non-blocking code paths (part 1)
Alan.Bateman at oracle.com
Thu Feb 22 19:08:41 UTC 2018
I mentioned in a thread here earlier this month that I have a number of
patches to reduce the complexity and overhead of supporting async close
and interrupt in the selectable channel implementations. All combined,
there are a lot of changes but are easy to split into a series of
smaller patches that are easier to test and review.
The patch here changes the SocketChannel and ServerSocketChannel
implementations so that channels configured non-blocking don't set the
hook for Thread.interrupt or don't track the threads potentially
blocking in I/O operations. The blocking case is improved too by
reducing, at least for the SocketChannel implementation, the locking
around the blocking calls. All the locking is consistent now, something
that will be clearer once the changes to DatagramChannel and the Pipe.*
implementations are discussed.
Simplification of the read/write/accept/connect/finishConnect methods
means that the implCloseSelectableChannel has to handle both the
blocking and non-blocking cases but it's not too complicated.
The socket adaptors have also changed so that they do timed operations
(Socket setSoTimeout and friends) with the channel configured blocking.
This it to avoid an explosion of scenarios (and complexity) that arises
when trying to be both blocking and non-blocking at the same time.
In terms of compatibility, there are two behavioral changes:
1. If a thread's interrupt status is set and it invokes an I/O method on
a channel configured non-blocking then the channel will not be closed.
The original specification was vague on this point as it focused on
threads blocking in I/O operations. Several people have complained
bitterly over the years about the existing behavior so they will welcome
this change. I haven't found anything yet that depends on long standing
behavior but we will need to track this in a CSR anyway.
2. configureBlocking will now block if there are pending I/O operations.
The spec has always stated that it may block so it should not be a
surprise but there may be some cases where code attempts to change a
channel to non-blocking while another thread is doing on a blocking I/O
operation on the channel. This method now coordinates with channel
closing, something that has never been right in the implementation.
The webrev with the patch is here:
More information about the nio-dev