--- /dev/null Tue Dec 28 12:15:45 2010 +++ new/jdk/src/solaris/classes/sun/nio/ch/EPollSelectorImpl.java Tue Dec 28 12:15:45 2010 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.nio.ch; + +import java.io.IOException; +import java.nio.channels.*; +import java.nio.channels.spi.*; +import java.util.*; +import sun.misc.*; + +/** + * An implementation of Selector for Linux 2.6+ kernels that uses + * the epoll event notification facility. + */ +class EPollSelectorImpl + extends SelectorImpl +{ + + // File descriptors used for interrupt + protected int fd0; + protected int fd1; + + // The poll object + EPollArrayWrapper pollWrapper; + + // Maps from file descriptors to keys + private Map fdToKey; + + // True if this Selector has been closed + private volatile boolean closed = false; + + // Lock for interrupt triggering and clearing + private Object interruptLock = new Object(); + private boolean interruptTriggered = false; + + /** + * Package private constructor called by factory method in + * the abstract superclass Selector. + */ + EPollSelectorImpl(SelectorProvider sp) { + super(sp); + long pipeFds = IOUtil.makePipe(false); + fd0 = (int) (pipeFds >>> 32); + fd1 = (int) pipeFds; + pollWrapper = new EPollArrayWrapper(); + pollWrapper.initInterrupt(fd0, fd1); + fdToKey = new HashMap(); + } + + protected int doSelect(long timeout) + throws IOException + { + if (closed) + throw new ClosedSelectorException(); + processDeregisterQueue(); + try { + begin(); + pollWrapper.poll(timeout); + } finally { + end(); + } + processDeregisterQueue(); + int numKeysUpdated = updateSelectedKeys(); + if (pollWrapper.interrupted()) { + // Clear the wakeup pipe + pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0); + synchronized (interruptLock) { + pollWrapper.clearInterrupted(); + IOUtil.drain(fd0); + interruptTriggered = false; + } + } + return numKeysUpdated; + } + + /** + * Update the keys whose fd's have been selected by the epoll. + * Add the ready keys to the ready queue. + */ + private int updateSelectedKeys() { + int entries = pollWrapper.updated; + int numKeysUpdated = 0; + for (int i=0; i i = keys.iterator(); + while (i.hasNext()) { + SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); + deregister(ski); + SelectableChannel selch = ski.channel(); + if (!selch.isOpen() && !selch.isRegistered()) + ((SelChImpl)selch).kill(); + i.remove(); + } + + fd0 = -1; + fd1 = -1; + } + + protected void implRegister(SelectionKeyImpl ski) { + if (closed) + throw new ClosedSelectorException(); + SelChImpl ch = ski.channel; + fdToKey.put(Integer.valueOf(ch.getFDVal()), ski); + pollWrapper.add(ch); + keys.add(ski); + } + + protected void implDereg(SelectionKeyImpl ski) throws IOException { + assert (ski.getIndex() >= 0); + SelChImpl ch = ski.channel; + int fd = ch.getFDVal(); + fdToKey.remove(Integer.valueOf(fd)); + pollWrapper.release(ch); + ski.setIndex(-1); + keys.remove(ski); + selectedKeys.remove(ski); + deregister((AbstractSelectionKey)ski); + SelectableChannel selch = ski.channel(); + if (!selch.isOpen() && !selch.isRegistered()) + ((SelChImpl)selch).kill(); + } + + void putEventOps(SelectionKeyImpl sk, int ops) { + if (closed) + throw new ClosedSelectorException(); + pollWrapper.setInterest(sk.channel, ops); + } + + public Selector wakeup() { + synchronized (interruptLock) { + if (!interruptTriggered) { + pollWrapper.interrupt(); + interruptTriggered = true; + } + } + return this; + } + + static { + Util.load(); + } + +}