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.


If we go ahead with this then it will need a CSR and release note.


More information about the nio-dev mailing list