
com.threerings.nio.SelectorIterable Maven / Gradle / Ivy
//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2011 Three Rings Design, Inc., All Rights Reserved
// http://code.google.com/p/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.nio;
import static com.threerings.NaryaLog.log;
import java.util.Collections;
import java.util.Iterator;
import java.util.Set;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import com.google.common.collect.Iterators;
/**
* Exposes selected keys from {@link Selector#selectedKeys()} as an Iterable, removing them from the
* selected set as they're iterated over.
*/
public class SelectorIterable
implements Iterable
{
/** The maximum allowed consecutive select() failures, after which we will declare ourselves
* irreparably hosed. */
public static final int MAX_SELECT_FAILURES = 20;
/**
* An interface for hearing about catastrophic selection failure. If select fails (in a
* non-expected way) more than {@link #MAX_SELECT_FAILURES} times in a row, this interface will
* be notified. This allows a server to reboot itself in an orderly manner, rather than
* continue in an inoperable state.
*/
public interface SelectFailureHandler {
/** Called to report a select() failure. */
void handleSelectFailure (Exception e);
}
/**
* Creates an iterable for the given selector's selectedKeys.
* @param selectLoopTime - the amount of time to wait in select, or 0 to skip the wait at all.
* @param handler - a callback for the Selector going awol.
*/
public SelectorIterable (Selector selector, int selectLoopTime, SelectFailureHandler handler)
{
_selector = selector;
_selectLoopTime = selectLoopTime;
_failureHandler = handler;
}
// from interface Iterable
public Iterator iterator ()
{
return Iterators.consumingIterator(select().iterator());
}
protected Set select ()
{
try {
// log.debug("Selecting from " + _selector.keys() + " (" + _selectLoopTime + ").");
// check for incoming network events
int eventCount =
_selectLoopTime == 0 ? _selector.selectNow() : _selector.select(_selectLoopTime);
Set ready = _selector.selectedKeys();
if (eventCount == 0 && ready.size() != 0) {
log.warning("select() returned no selected sockets, but there are "
+ ready.size() + " in the ready set.");
}
// clear the runtime error count
_runtimeExceptionCount = 0;
return ready;
} catch (IOException ioe) {
log.warning("Failure select()ing", "ioe", ioe);
} catch (RuntimeException re) {
// this block of code deals with a bug in the _selector that we observed on 2005-05-02,
// instead of looping indefinitely after things go pear-shaped, shut us down in an
// orderly fashion
log.warning("Failure select()ing.", re);
if (_runtimeExceptionCount++ >= MAX_SELECT_FAILURES) {
_failureHandler.handleSelectFailure(re);
}
}
return Collections.emptySet();
}
protected int _runtimeExceptionCount;
protected final int _selectLoopTime;
protected final Selector _selector;
protected final SelectFailureHandler _failureHandler;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy