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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.IOException;
29 import java.nio.channels.*;
30 import java.nio.channels.spi.*;
31 import java.util.*;
32 import sun.misc.*;
33
34 /**
35 * An implementation of Selector for Linux 2.6+ kernels that uses
36 * the epoll event notification facility.
37 */
38 class EPollSelectorImpl
39 extends SelectorImpl
40 {
41
42 // File descriptors used for interrupt
43 protected int fd0;
44 protected int fd1;
45
46 // The poll object
47 EPollArrayWrapper pollWrapper;
48
49 // Maps from file descriptors to keys
50 private Map<Integer,SelectionKeyImpl> fdToKey;
51
52 // True if this Selector has been closed
54
55 // Lock for interrupt triggering and clearing
56 private final Object interruptLock = new Object();
57 private boolean interruptTriggered = false;
58
59 /**
60 * Package private constructor called by factory method in
61 * the abstract superclass Selector.
62 */
63 EPollSelectorImpl(SelectorProvider sp) throws IOException {
64 super(sp);
65 long pipeFds = IOUtil.makePipe(false);
66 fd0 = (int) (pipeFds >>> 32);
67 fd1 = (int) pipeFds;
68 pollWrapper = new EPollArrayWrapper();
69 pollWrapper.initInterrupt(fd0, fd1);
70 fdToKey = new HashMap<>();
71 }
72
73 protected int doSelect(long timeout) throws IOException {
74 if (closed)
75 throw new ClosedSelectorException();
76 processDeregisterQueue();
77 try {
78 begin();
79 pollWrapper.poll(timeout);
80 } finally {
81 end();
82 }
83 processDeregisterQueue();
84 int numKeysUpdated = updateSelectedKeys();
85 if (pollWrapper.interrupted()) {
86 // Clear the wakeup pipe
87 pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
88 synchronized (interruptLock) {
89 pollWrapper.clearInterrupted();
90 IOUtil.drain(fd0);
91 interruptTriggered = false;
92 }
93 }
94 return numKeysUpdated;
95 }
96
97 /**
98 * Update the keys whose fd's have been selected by the epoll.
99 * Add the ready keys to the ready queue.
100 */
101 private int updateSelectedKeys() {
102 int entries = pollWrapper.updated;
103 int numKeysUpdated = 0;
104 for (int i=0; i<entries; i++) {
105 int nextFD = pollWrapper.getDescriptor(i);
106 SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(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 return;
129 closed = true;
130
131 // prevent further wakeup
132 synchronized (interruptLock) {
133 interruptTriggered = true;
134 }
135
136 FileDispatcherImpl.closeIntFD(fd0);
|
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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.nio.ch;
27
28 import java.io.IOException;
29 import java.nio.channels.*;
30 import java.nio.channels.spi.*;
31 import java.util.*;
32 import java.util.function.Consumer;
33
34 /**
35 * An implementation of Selector for Linux 2.6+ kernels that uses
36 * the epoll event notification facility.
37 */
38 class EPollSelectorImpl
39 extends SelectorImpl
40 {
41
42 // File descriptors used for interrupt
43 protected int fd0;
44 protected int fd1;
45
46 // The poll object
47 EPollArrayWrapper pollWrapper;
48
49 // Maps from file descriptors to keys
50 private Map<Integer,SelectionKeyImpl> fdToKey;
51
52 // True if this Selector has been closed
54
55 // Lock for interrupt triggering and clearing
56 private final Object interruptLock = new Object();
57 private boolean interruptTriggered = false;
58
59 /**
60 * Package private constructor called by factory method in
61 * the abstract superclass Selector.
62 */
63 EPollSelectorImpl(SelectorProvider sp) throws IOException {
64 super(sp);
65 long pipeFds = IOUtil.makePipe(false);
66 fd0 = (int) (pipeFds >>> 32);
67 fd1 = (int) pipeFds;
68 pollWrapper = new EPollArrayWrapper();
69 pollWrapper.initInterrupt(fd0, fd1);
70 fdToKey = new HashMap<>();
71 }
72
73 protected int doSelect(long timeout) throws IOException {
74 pollEpollWrapper(timeout);
75 int numKeysUpdated = updateSelectedKeys();
76 clearWakeupPipeIfInterrupted();
77 return numKeysUpdated;
78 }
79
80 @Override
81 protected int doSelect(Consumer<SelectionKey> handler, long timeout) throws IOException {
82 Objects.requireNonNull(handler);
83 pollEpollWrapper(timeout);
84 final int entries = pollWrapper.updated;
85 int numKeysUpdated = 0;
86 try {
87 for (int i=0; i<entries; i++) {
88 final int nextFD = pollWrapper.getDescriptor(i);
89 final SelectionKeyImpl ski = fdToKey.get(nextFD);
90 // ski is null in the case of an interrupt
91 if (ski != null) {
92 final int readyOperations = pollWrapper.getEventOps(i);
93 ski.channel.translateAndSetReadyOps(readyOperations, ski);
94 if (ski.hasOps()) {
95 handler.accept(ski);
96 numKeysUpdated++;
97 }
98 }
99 }
100 } finally {
101 clearWakeupPipeIfInterrupted();
102 }
103 return numKeysUpdated;
104 }
105
106 private void pollEpollWrapper(long timeout) throws IOException {
107 if (closed)
108 throw new ClosedSelectorException();
109 processDeregisterQueue();
110 try {
111 begin();
112 pollWrapper.poll(timeout);
113 } finally {
114 end();
115 }
116 processDeregisterQueue();
117 }
118
119 private void clearWakeupPipeIfInterrupted() throws IOException {
120 if (pollWrapper.interrupted()) {
121 // Clear the wakeup pipe
122 pollWrapper.putEventOps(pollWrapper.interruptedIndex(), 0);
123 synchronized (interruptLock) {
124 pollWrapper.clearInterrupted();
125 IOUtil.drain(fd0);
126 interruptTriggered = false;
127 }
128 }
129 }
130
131 /**
132 * Update the keys whose fd's have been selected by the epoll.
133 * Add the ready keys to the ready queue.
134 */
135 private int updateSelectedKeys() {
136 int entries = pollWrapper.updated;
137 int numKeysUpdated = 0;
138 for (int i=0; i<entries; i++) {
139 int nextFD = pollWrapper.getDescriptor(i);
140 SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
141 // ski is null in the case of an interrupt
142 if (ski != null) {
143 int readyOperations = pollWrapper.getEventOps(i);
144 if (selectedKeys.contains(ski)) {
145 if (ski.channel.translateAndSetReadyOps(readyOperations, ski)) {
146 numKeysUpdated++;
147 }
148 } else {
149 ski.channel.translateAndSetReadyOps(readyOperations, ski);
150 if (ski.hasOps()) {
151 selectedKeys.add(ski);
152 numKeysUpdated++;
153 }
154 }
155 }
156 }
157 return numKeysUpdated;
158 }
159
160 protected void implClose() throws IOException {
161 if (closed)
162 return;
163 closed = true;
164
165 // prevent further wakeup
166 synchronized (interruptLock) {
167 interruptTriggered = true;
168 }
169
170 FileDispatcherImpl.closeIntFD(fd0);
|