views:

191

answers:

2

In my implementation of Java NIO I have not been able to get SelectionKey.attach() to work. Basically, once clients connect (OP_ACCEPT interest ops) I add them to a map where their IP address maps to an object that maintains state for the client. Then, when an OP_READ occurs, I again retrieve the client's IP address, and this time get the value from the map and get the client's state object that way.

The problem here is that I have to do a map lookup EVERY TIME data is read from the network. There is a lot of wasted work going on there. So, I was thrilled to see that you can attach an arbitrary object type to a SelectionKey, which should be easily retrieved when you call SelectionKey.attachment(), even if we are now handling a different event (retrieved during OP_READ versus put into the map during OP_ACCEPT).

The problem is that it doesn't work. When I retrieve the attachment, it is always null. And if I set up the attachment via attach() and then immediately call attachment(), it does work. Somehow between different events, it loses its association.

I'm sorry, my code is a bit long to post here, but if you look at the comments in this thread: link text ...You will see that some others have basically come to the same conclusion: that attach() and attachment() don't work, and never have.

Is there a trick to get it to work, or am I stuck with the evil overhead necessary of manually doing a lookup in a map EVERY TIME there is a new read event to handle?

Finally, is there a way to "wrap" SelectionKey in a new subclass that will properly handle attach() and attachment()?

Thanks!

A: 

There is no CR in your linked page, and I can't see anything on bugs.sun.com. However, attach/attachment is very simple code (although slightly more complicated after my bug. My guess is that you are getting a different SelectionKey, so trying to wrap it would be pointless.

Tom Hawtin - tackline
+3  A: 

I have successfully attached objects to SelectionKeys without any problems, but only from the same event. For example the first time I get an OP_READ, I attach an object to the SelectionKey and on subsequent reads I retrieve it, and it works fine. Maybe OP_ACCEPT and OP_READ handle different keys because they're different events, but I think the SelectionKey should be the same for the same connection... however if you make different connections even from the same IP you will get different SelectionKeys.

UPDATE: I just checked my code and there is something very important: I didn't call attach() at all; I used the SelectableChannel.register(Selector sel, int ops, Object att) method. If you do that, subsequent calls to attachment() on the SelectionKey will work.

Chochos
Thanks so much! I think the combination of things you mentioned might lead to a solution that works every time! :) Plus, if attachment() fails, I still have the option of doing the more costly map look-up, so I can write it to be robust even if the attachment is lost! Thanks!
ZenBlender
This is very handy. I was able to remove a HashMap from my NIO implementation. Thanks!
Nighthawk