tags:

views:

169

answers:

2

Hello,

using java.nio one has to register interest in operations via the SelectableChannel:

SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask)

Registering Interest:

  • overwriting the existing SelectionKey by executing SelectableChannel.register with new Ops
  • VS. updating the existing SelectionKey with key.interestOps(key.interestOps() | newOp)

Unregistering Interest:

  • SelectionKey.cancel and SelectableChannel.register with new Ops
  • VS. updating the existing SelectionKey like above

Are there any pros & cons?

Thanks

A: 

I would update the existing interestOps using the or-operator as you suggest. I would be concerned about missing selections if I (temporarily) canceled the selection key.

Besides, cancel+reregister just seems more complicated than updating.

Unless you have an underlying logical reason for registering with new ops, I would suggest to always go with update.

aioobe
+1  A: 

If you always dispatch execution to a thread pool after select() return, you may wish to immediately cancel the key, since you loose the control over the time the Runnable will execute.

Ex.: If you perform the next select() before canceling the previous key (the thread is still waiting for execution), it will be valid yet, causing another thread to carry the already dispatched key. If one of these threads cancels the key, the other will get a CancelledKeyException besides introducing unexpected behavior.

Even if you cancel the key, a thread may register the same channel (update selection keys) before the channel become unregistered (due to your previous key.cancel()). What, again, will cause a CancelledKeyException.

To get rid of this trap, you may want to handle events always in the next loop:

while (true) { // true or something less risky
    //for each pendingTasks call
    pool.execute(task);
    Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
    while (iter.hasNext()) {
        SelectionKey key = iter.next();
        iter.remove();
        key.cancel();
        //store dispatch for the next while iteration
        pendingTasks.add(task); // do not execute tasks before next select()
    }
    selector.select(TIMEOUT); // or selectNow if there are 
                              //any pending events to handle.
}

Firt execution will, almost, never return keys, but the select() at the end of your loop MAY guarantee the channel of canceled key be unregistered (bear it's up to your impl) from selector.

However, if you are simply executing a task in the same thread you listen to your selector events, updating sounds easy and safer.

paulosuzart
you would change the timout of your selector if there are tasks still running on your thread pool. If you use a big timout in your select() you can cause blocked threads for registering new/existing channels to selector.
paulosuzart