001: /*
002: * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.nio.ch;
027:
028: import java.io.IOException;
029: import java.nio.channels.*;
030: import java.nio.channels.spi.*;
031: import java.util.*;
032: import sun.misc.*;
033:
034: /**
035: * An implementation of Selector for Linux 2.6+ kernels that uses
036: * the epoll event notification facility.
037: */
038: class EPollSelectorImpl extends SelectorImpl {
039:
040: // File descriptors used for interrupt
041: protected int fd0;
042: protected int fd1;
043:
044: // The poll object
045: EPollArrayWrapper pollWrapper;
046:
047: // Maps from file descriptors to keys
048: private HashMap fdToKey;
049:
050: // True if this Selector has been closed
051: private boolean closed = false;
052:
053: // Lock for interrupt triggering and clearing
054: private Object interruptLock = new Object();
055: private boolean interruptTriggered = false;
056:
057: /**
058: * Package private constructor called by factory method in
059: * the abstract superclass Selector.
060: */
061: EPollSelectorImpl(SelectorProvider sp) {
062: super (sp);
063: int[] fdes = new int[2];
064: IOUtil.initPipe(fdes, false);
065: fd0 = fdes[0];
066: fd1 = fdes[1];
067: pollWrapper = new EPollArrayWrapper();
068: pollWrapper.initInterrupt(fd0, fd1);
069: fdToKey = new HashMap();
070: }
071:
072: protected int doSelect(long timeout) throws IOException {
073: if (closed)
074: throw new ClosedSelectorException();
075: processDeregisterQueue();
076: try {
077: begin();
078: pollWrapper.poll(timeout);
079: } finally {
080: end();
081: }
082: processDeregisterQueue();
083: int numKeysUpdated = updateSelectedKeys();
084: if (pollWrapper.interrupted()) {
085: // Clear the wakeup pipe
086: pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
087: synchronized (interruptLock) {
088: pollWrapper.clearInterrupted();
089: IOUtil.drain(fd0);
090: interruptTriggered = false;
091: }
092: }
093: return numKeysUpdated;
094: }
095:
096: /**
097: * Update the keys whose fd's have been selected by the epoll.
098: * Add the ready keys to the ready queue.
099: */
100: private int updateSelectedKeys() {
101: int entries = pollWrapper.updated;
102: int numKeysUpdated = 0;
103: for (int i = 0; i < entries; i++) {
104: int nextFD = pollWrapper.getDescriptor(i);
105: SelectionKeyImpl ski = (SelectionKeyImpl) fdToKey
106: .get(new Integer(nextFD));
107: // ski is null in the case of an interrupt
108: if (ski != null) {
109: int rOps = pollWrapper.getEventOps(i);
110: if (selectedKeys.contains(ski)) {
111: if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
112: numKeysUpdated++;
113: }
114: } else {
115: ski.channel.translateAndSetReadyOps(rOps, ski);
116: if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
117: selectedKeys.add(ski);
118: numKeysUpdated++;
119: }
120: }
121: }
122: }
123: return numKeysUpdated;
124: }
125:
126: protected void implClose() throws IOException {
127: if (!closed) {
128: closed = true;
129:
130: // prevent further wakeup
131: synchronized (interruptLock) {
132: interruptTriggered = true;
133: }
134:
135: FileDispatcher.closeIntFD(fd0);
136: FileDispatcher.closeIntFD(fd1);
137: if (pollWrapper != null) {
138:
139: pollWrapper.release(fd0);
140: pollWrapper.closeEPollFD();
141: pollWrapper = null;
142: selectedKeys = null;
143:
144: // Deregister channels
145: Iterator i = keys.iterator();
146: while (i.hasNext()) {
147: SelectionKeyImpl ski = (SelectionKeyImpl) i.next();
148: deregister(ski);
149: SelectableChannel selch = ski.channel();
150: if (!selch.isOpen() && !selch.isRegistered())
151: ((SelChImpl) selch).kill();
152: i.remove();
153: }
154: }
155: fd0 = -1;
156: fd1 = -1;
157: }
158: }
159:
160: protected void implRegister(SelectionKeyImpl ski) {
161: int fd = IOUtil.fdVal(ski.channel.getFD());
162: fdToKey.put(new Integer(fd), ski);
163: pollWrapper.add(fd);
164: keys.add(ski);
165: }
166:
167: protected void implDereg(SelectionKeyImpl ski) throws IOException {
168: assert (ski.getIndex() >= 0);
169: int fd = ski.channel.getFDVal();
170: fdToKey.remove(new Integer(fd));
171: pollWrapper.release(fd);
172: ski.setIndex(-1);
173: keys.remove(ski);
174: selectedKeys.remove(ski);
175: deregister((AbstractSelectionKey) ski);
176: SelectableChannel selch = ski.channel();
177: if (!selch.isOpen() && !selch.isRegistered())
178: ((SelChImpl) selch).kill();
179: }
180:
181: void putEventOps(SelectionKeyImpl sk, int ops) {
182: int fd = IOUtil.fdVal(sk.channel.getFD());
183: pollWrapper.setInterest(fd, ops);
184: }
185:
186: public Selector wakeup() {
187: synchronized (interruptLock) {
188: if (!interruptTriggered) {
189: pollWrapper.interrupt();
190: interruptTriggered = true;
191: }
192: }
193: return this ;
194: }
195:
196: static {
197: Util.load();
198: }
199:
200: }
|