Callback Based Selectors

Alan Bateman Alan.Bateman at
Wed Mar 14 14:05:58 UTC 2018

On 16/01/2016 11:14, Richard Warburton wrote:
> Hi gents,
> I've prototyped a callback based addition to the NIO Selector, which 
> I've previously talked through a bit with Alan Bateman. The goal of 
> the callback based selector is to avoid the current pattern of calling 
> select/selectNow on a Nio selector and then having to iterate over a 
> hashmap produced. This pattern being quite object allocation heavy for 
> a critical path and also involving obtaining and releasing multiple 
> locks. I'd like to propose that the following patch, which adds the 
> ability to perform a select on a Selector that takes a callback handler.
> <>
> I'm happy to iterate on the patch a bit based upon people's feedback 
> and discuss any potential concerns or issues that you may have with 
> the patch. Looking forward to hearing your feedback.
This one has been on my list for a long time to study more closely. When 
we discussed it here in 2016 I had concerns about invoking a consumer 
while synchronized on the selector and other locks. It has grown on my a 
bit so I spent a bit of time recently to work through the  implications, 
both spec and implementation.

For the spec:  The Selector API describes selection operations in its 
class description and it's important to keep that consistent when 
introducing a new way to be notified of channels ready for I/O operations.

The action is arbitrary code and we have to assume it will behave as if 
it's a bull in a china shop. It might attempt another selection 
operation on the same selector, it might close the selector, it might 
change the interest set or cancel a key for a channel registered with 
the selector but not yet seen by the consumer. All of these scenarios 
need consideration.

Locking was mostly ignored in the original prototype but the locking has 
to be consistent with how the existing selection operations are 
specified. The main reason is processing the cancelled-key set means 
removing keys from the key set and selected-key set. On the surface, the 
new methods should not care about the selected-key set but they have to 
maintain the invariant that the selected-key set is always a subset of 
the selector's key set.

Another point of detail is that the action may need to be called more 
than once for the same key but different ready sets. We have this with 
the kqueue implementation where events for read and write are registered 
with different filters. Other implementation might maintain separate 
poll arrays for read and write events.

In terms of performance, the main benefit is that avoids adding keys to 
the selected-key set, only to be removed almost immediately by the code 
doing the select. This avoids garbage so helps the GC too. If we go 
ahead with these methods then it's important to get a good range of 
performance data and also see whether a specialized set to support the 
usage pattern of the selected-key set might be alternative to 
introducing new APIs.

I've put a webrev here with candidate changes to the Selector API. It's 
one select(Consumer<SelectionKey>, timeout) for now, the 
select(Consumer<SelectionKey>) and selectNow(Consumer<SelectionKey>) 
variants are easy to add if needed. The webrev has a default 
implementation based on the existing API, and then implementations for 
macOS and Linux. Other platforms could be added later of course. I've 
also included a test that covers most of the scenarios.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the nio-dev mailing list