public boolean select(RubyIO io, int ops) {
Channel channel = io.getChannel();
if (channel instanceof SelectableChannel) {
SelectableChannel selectable = (SelectableChannel)channel;
synchronized (selectable.blockingLock()) {
boolean oldBlocking = selectable.isBlocking();
try {
selectable.configureBlocking(false);
io.addBlockingThread(this);
currentSelector = selectable.provider().openSelector();
SelectionKey key = selectable.register(currentSelector, ops);
int result = currentSelector.select();
// check for thread events, in case we've been woken up to die
pollThreadEvents();
if (result == 1) {
Set<SelectionKey> keySet = currentSelector.selectedKeys();
if (keySet.iterator().next() == key) {
return true;
}
}
return false;
} catch (IOException ioe) {
throw io.getRuntime().newRuntimeError("Error with selector: " + ioe);
} finally {
if (currentSelector != null) {
try {
currentSelector.close();
} catch (IOException ioe) {
throw io.getRuntime().newRuntimeError("Could not close selector");
}
}
currentSelector = null;
io.removeBlockingThread(this);
try {
selectable.configureBlocking(oldBlocking);
} catch (IOException ioe) {
// ignore; I don't like doing it, but it seems like we
// really just need to make all channels non-blocking by
// default and use select when implementing blocking ops,
// so if this remains set non-blocking, perhaps it's not