8201315: (se) Allow SelectableChannel.register to be invoked while selection operation is in progress
Alan Bateman
Alan.Bateman at oracle.com
Mon Apr 9 17:56:25 UTC 2018
One of the issues brought up in the "Callback Based Selectors"
discussion is that the register methods are specified to block if there
is a selection operation in progress. This leads to the idiom of the
gate object to coordinate new registrations with selection operations.
I've looked into the implications of changing the existing API so that
register can be invoked while a selection operation is in operation. The
approach that I think strikes a balance between concurrency and
preserving compatibility is to re-specify the Selector's key set to
support concurrent operations, leaving the selected-key and
cancelled-key set as is.
To re-cap: the order that the key sets are locked is (i) keys, (ii)
selected-keys, and (iii) cancelled-keys. We can't do anything that would
result in these sets being locked in a different order as it risks
deadlocking with user code, e.g. code that synchronizes on keys and
invokes cancel for each key.
The steps in a selection operation that access the sets are:
1. Processing cancelled keys: removes the cancelled keys from each of
the sets
2. Processing events: adds keys to the selected-key set
It would be feasible to limit the scope of the locking to just these
steps but it adds a lot of locking to preserve the specified ordering,
more so because the cancelled-keys set can be processed twice (before
and after polling for readiness events).
Another point is that we have to be conservative with the selected-key
set as that is the most user facing of the sets. Existing code will
synchronize on this set when processing selected-keys. I think it would
be too risky to not synchronize on the selected-key set.
The webrev below has the spec changes with the proposal. The changes
mean that register can be invoked while a selection operation is in
progress, the new registration will come into effect at the next
selection operation. Same thing for interestOps where the change will
also come into effect at the next selection operation. It means that
register, interestOps and cancel can be followed by wakeup without other
coordination or explicit locking.
There are two aspect to the compatibility implications:
1. 3rd party Selector (or rather SelectorProvider) implementations will
need to be updated. These seem few and far between so I'm not too
concerned about this.
2. Code that synchronizes on the key set in order to get a snapshot of
the current registrations. I need help in assessing this but I haven't
found any existing code so far where this is an issue. In general, there
doesn't seem to be a lot of code synchronizing on the key set, all the
action is instead processing the selected-key set.
http://cr.openjdk.java.net/~alanb/8201315/webrev/index.html
If we go ahead with this then it will need a CSR and release note.
-Alan.
More information about the nio-dev
mailing list