001: /*
002: * Copyright 2001-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 Solaris.
036: */
037: class DevPollSelectorImpl extends SelectorImpl {
038:
039: // File descriptors used for interrupt
040: protected int fd0;
041: protected int fd1;
042:
043: // The poll object
044: DevPollArrayWrapper pollWrapper;
045:
046: // The number of valid channels in this Selector's poll array
047: private int totalChannels;
048:
049: // Maps from file descriptors to keys
050: private HashMap fdToKey;
051:
052: // True if this Selector has been closed
053: private boolean closed = false;
054:
055: // Lock for interrupt triggering and clearing
056: private Object interruptLock = new Object();
057: private boolean interruptTriggered = false;
058:
059: /**
060: * Package private constructor called by factory method in
061: * the abstract superclass Selector.
062: */
063: DevPollSelectorImpl(SelectorProvider sp) {
064: super (sp);
065: int[] fdes = new int[2];
066: IOUtil.initPipe(fdes, false);
067: fd0 = fdes[0];
068: fd1 = fdes[1];
069: pollWrapper = new DevPollArrayWrapper();
070: pollWrapper.initInterrupt(fd0, fd1);
071: fdToKey = new HashMap();
072: totalChannels = 1;
073: }
074:
075: protected int doSelect(long timeout) throws IOException {
076: if (closed)
077: throw new ClosedSelectorException();
078: processDeregisterQueue();
079: try {
080: begin();
081: pollWrapper.poll(timeout);
082: } finally {
083: end();
084: }
085: processDeregisterQueue();
086: int numKeysUpdated = updateSelectedKeys();
087: if (pollWrapper.interrupted()) {
088: // Clear the wakeup pipe
089: pollWrapper.putReventOps(pollWrapper.interruptedIndex(), 0);
090: synchronized (interruptLock) {
091: pollWrapper.clearInterrupted();
092: IOUtil.drain(fd0);
093: interruptTriggered = false;
094: }
095: }
096: return numKeysUpdated;
097: }
098:
099: /**
100: * Update the keys whose fd's have been selected by the devpoll
101: * driver. Add the ready keys to the ready queue.
102: */
103: private int updateSelectedKeys() {
104: int entries = pollWrapper.updated;
105: int numKeysUpdated = 0;
106: for (int i = 0; i < entries; i++) {
107: int nextFD = pollWrapper.getDescriptor(i);
108: SelectionKeyImpl ski = (SelectionKeyImpl) fdToKey
109: .get(new Integer(nextFD));
110: // ski is null in the case of an interrupt
111: if (ski != null) {
112: int rOps = pollWrapper.getReventOps(i);
113: if (selectedKeys.contains(ski)) {
114: if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
115: numKeysUpdated++;
116: }
117: } else {
118: ski.channel.translateAndSetReadyOps(rOps, ski);
119: if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
120: selectedKeys.add(ski);
121: numKeysUpdated++;
122: }
123: }
124: }
125: }
126: return numKeysUpdated;
127: }
128:
129: protected void implClose() throws IOException {
130: if (!closed) {
131: closed = true;
132:
133: // prevent further wakeup
134: synchronized (interruptLock) {
135: interruptTriggered = true;
136: }
137:
138: FileDispatcher.closeIntFD(fd0);
139: FileDispatcher.closeIntFD(fd1);
140: if (pollWrapper != null) {
141:
142: pollWrapper.release(fd0);
143: pollWrapper.closeDevPollFD();
144: pollWrapper = null;
145: selectedKeys = null;
146:
147: // Deregister channels
148: Iterator i = keys.iterator();
149: while (i.hasNext()) {
150: SelectionKeyImpl ski = (SelectionKeyImpl) i.next();
151: deregister(ski);
152: SelectableChannel selch = ski.channel();
153: if (!selch.isOpen() && !selch.isRegistered())
154: ((SelChImpl) selch).kill();
155: i.remove();
156: }
157: totalChannels = 0;
158:
159: }
160: fd0 = -1;
161: fd1 = -1;
162: }
163: }
164:
165: protected void implRegister(SelectionKeyImpl ski) {
166: int fd = IOUtil.fdVal(ski.channel.getFD());
167: fdToKey.put(new Integer(fd), ski);
168: totalChannels++;
169: keys.add(ski);
170: }
171:
172: protected void implDereg(SelectionKeyImpl ski) throws IOException {
173: int i = ski.getIndex();
174: assert (i >= 0);
175: int fd = ski.channel.getFDVal();
176: fdToKey.remove(new Integer(fd));
177: pollWrapper.release(fd);
178: totalChannels--;
179: ski.setIndex(-1);
180: keys.remove(ski);
181: selectedKeys.remove(ski);
182: deregister((AbstractSelectionKey) ski);
183: SelectableChannel selch = ski.channel();
184: if (!selch.isOpen() && !selch.isRegistered())
185: ((SelChImpl) selch).kill();
186: }
187:
188: void putEventOps(SelectionKeyImpl sk, int ops) {
189: int fd = IOUtil.fdVal(sk.channel.getFD());
190: pollWrapper.setInterest(fd, ops);
191: }
192:
193: public Selector wakeup() {
194: synchronized (interruptLock) {
195: if (!interruptTriggered) {
196: pollWrapper.interrupt();
197: interruptTriggered = true;
198: }
199: }
200: return this ;
201: }
202:
203: static {
204: Util.load();
205: }
206:
207: }
|