blob: 47911b4736d231ea4a0842dacaeec9a5f1924770 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.nio.ch;
27
28import java.io.IOException;
29import java.nio.channels.*;
30import java.nio.channels.spi.*;
31import java.util.*;
32import sun.misc.*;
33
34
35/**
36 * An implementation of Selector for Linux 2.6+ kernels that uses
37 * the epoll event notification facility.
38 */
39class EPollSelectorImpl
40 extends SelectorImpl
41{
42
43 // File descriptors used for interrupt
44 protected int fd0;
45 protected int fd1;
46
47 // The poll object
48 EPollArrayWrapper pollWrapper;
49
50 // Maps from file descriptors to keys
51 private HashMap fdToKey;
52
53 // True if this Selector has been closed
54 private boolean closed = false;
55
56 // Lock for interrupt triggering and clearing
57 private Object interruptLock = new Object();
58 private boolean interruptTriggered = false;
59
60 /**
61 * Package private constructor called by factory method in
62 * the abstract superclass Selector.
63 */
64 EPollSelectorImpl(SelectorProvider sp) {
65 super(sp);
66 int[] fdes = new int[2];
67 IOUtil.initPipe(fdes, false);
68 fd0 = fdes[0];
69 fd1 = fdes[1];
70 pollWrapper = new EPollArrayWrapper();
71 pollWrapper.initInterrupt(fd0, fd1);
72 fdToKey = new HashMap();
73 }
74
75 protected int doSelect(long timeout)
76 throws IOException
77 {
78 if (closed)
79 throw new ClosedSelectorException();
80 processDeregisterQueue();
81 try {
82 begin();
83 pollWrapper.poll(timeout);
84 } finally {
85 end();
86 }
87 processDeregisterQueue();
88 int numKeysUpdated = updateSelectedKeys();
89 if (pollWrapper.interrupted()) {
90 // Clear the wakeup pipe
91 pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
92 synchronized (interruptLock) {
93 pollWrapper.clearInterrupted();
94 IOUtil.drain(fd0);
95 interruptTriggered = false;
96 }
97 }
98 return numKeysUpdated;
99 }
100
101 /**
102 * Update the keys whose fd's have been selected by the epoll.
103 * Add the ready keys to the ready queue.
104 */
105 private int updateSelectedKeys() {
106 int entries = pollWrapper.updated;
107 int numKeysUpdated = 0;
108 for (int i=0; i<entries; i++) {
109 int nextFD = pollWrapper.getDescriptor(i);
110 SelectionKeyImpl ski = (SelectionKeyImpl) fdToKey.get(
111 new Integer(nextFD));
112 // ski is null in the case of an interrupt
113 if (ski != null) {
114 int rOps = pollWrapper.getEventOps(i);
115 if (selectedKeys.contains(ski)) {
116 if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
117 numKeysUpdated++;
118 }
119 } else {
120 ski.channel.translateAndSetReadyOps(rOps, ski);
121 if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
122 selectedKeys.add(ski);
123 numKeysUpdated++;
124 }
125 }
126 }
127 }
128 return numKeysUpdated;
129 }
130
131 protected void implClose() throws IOException {
132 if (!closed) {
133 closed = true;
134
135 // prevent further wakeup
136 synchronized (interruptLock) {
137 interruptTriggered = true;
138 }
139
140 FileDispatcher.closeIntFD(fd0);
141 FileDispatcher.closeIntFD(fd1);
142 if (pollWrapper != null) {
143
144 pollWrapper.release(fd0);
145 pollWrapper.closeEPollFD();
146 pollWrapper = null;
147 selectedKeys = null;
148
149 // Deregister channels
150 Iterator i = keys.iterator();
151 while (i.hasNext()) {
152 SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
153 deregister(ski);
154 SelectableChannel selch = ski.channel();
155 if (!selch.isOpen() && !selch.isRegistered())
156 ((SelChImpl)selch).kill();
157 i.remove();
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 pollWrapper.add(fd);
169 keys.add(ski);
170 }
171
172 protected void implDereg(SelectionKeyImpl ski) throws IOException {
173 assert (ski.getIndex() >= 0);
174 int fd = ski.channel.getFDVal();
175 fdToKey.remove(new Integer(fd));
176 pollWrapper.release(fd);
177 ski.setIndex(-1);
178 keys.remove(ski);
179 selectedKeys.remove(ski);
180 deregister((AbstractSelectionKey)ski);
181 SelectableChannel selch = ski.channel();
182 if (!selch.isOpen() && !selch.isRegistered())
183 ((SelChImpl)selch).kill();
184 }
185
186 void putEventOps(SelectionKeyImpl sk, int ops) {
187 int fd = IOUtil.fdVal(sk.channel.getFD());
188 pollWrapper.setInterest(fd, ops);
189 }
190
191 public Selector wakeup() {
192 synchronized (interruptLock) {
193 if (!interruptTriggered) {
194 pollWrapper.interrupt();
195 interruptTriggered = true;
196 }
197 }
198 return this;
199 }
200
201 static {
202 Util.load();
203 }
204
205}