25 |
25 |
26 package sun.nio.ch; |
26 package sun.nio.ch; |
27 |
27 |
28 import java.io.IOException; |
28 import java.io.IOException; |
29 import java.nio.channels.ClosedSelectorException; |
29 import java.nio.channels.ClosedSelectorException; |
30 import java.nio.channels.SelectableChannel; |
|
31 import java.nio.channels.SelectionKey; |
|
32 import java.nio.channels.Selector; |
30 import java.nio.channels.Selector; |
33 import java.nio.channels.spi.SelectorProvider; |
31 import java.nio.channels.spi.SelectorProvider; |
34 import java.util.ArrayDeque; |
32 import java.util.ArrayDeque; |
35 import java.util.BitSet; |
|
36 import java.util.Deque; |
33 import java.util.Deque; |
37 import java.util.HashMap; |
34 import java.util.HashMap; |
38 import java.util.Iterator; |
|
39 import java.util.Map; |
35 import java.util.Map; |
40 import java.util.concurrent.TimeUnit; |
36 import java.util.concurrent.TimeUnit; |
41 |
37 |
42 import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS; |
38 import static sun.nio.ch.DevPollArrayWrapper.NUM_POLLFDS; |
43 import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE; |
39 import static sun.nio.ch.DevPollArrayWrapper.POLLREMOVE; |
57 private final int fd1; |
53 private final int fd1; |
58 |
54 |
59 // maps file descriptor to selection key, synchronize on selector |
55 // maps file descriptor to selection key, synchronize on selector |
60 private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>(); |
56 private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>(); |
61 |
57 |
62 // file descriptors registered with /dev/poll, synchronize on selector |
|
63 private final BitSet registered = new BitSet(); |
|
64 |
|
65 // pending new registrations/updates, queued by implRegister and putEventOps |
58 // pending new registrations/updates, queued by implRegister and putEventOps |
66 private final Object updateLock = new Object(); |
59 private final Object updateLock = new Object(); |
67 private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>(); |
60 private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>(); |
68 private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>(); |
61 private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>(); |
69 private final Deque<Integer> updateOps = new ArrayDeque<>(); |
62 private final Deque<Integer> updateEvents = new ArrayDeque<>(); |
70 |
63 |
71 // interrupt triggering and clearing |
64 // interrupt triggering and clearing |
72 private final Object interruptLock = new Object(); |
65 private final Object interruptLock = new Object(); |
73 private boolean interruptTriggered; |
66 private boolean interruptTriggered; |
74 |
67 |
97 @Override |
90 @Override |
98 protected int doSelect(long timeout) |
91 protected int doSelect(long timeout) |
99 throws IOException |
92 throws IOException |
100 { |
93 { |
101 assert Thread.holdsLock(this); |
94 assert Thread.holdsLock(this); |
|
95 boolean blocking = (timeout != 0); |
102 |
96 |
103 int numEntries; |
97 int numEntries; |
104 processUpdateQueue(); |
98 processUpdateQueue(); |
105 processDeregisterQueue(); |
99 processDeregisterQueue(); |
106 try { |
100 try { |
107 begin(); |
101 begin(blocking); |
108 numEntries = pollWrapper.poll(timeout); |
102 numEntries = pollWrapper.poll(timeout); |
109 } finally { |
103 } finally { |
110 end(); |
104 end(blocking); |
111 } |
105 } |
112 processDeregisterQueue(); |
106 processDeregisterQueue(); |
113 return updateSelectedKeys(numEntries); |
107 return updateSelectedKeys(numEntries); |
114 } |
108 } |
115 |
109 |
123 SelectionKeyImpl ski; |
117 SelectionKeyImpl ski; |
124 |
118 |
125 // new registrations |
119 // new registrations |
126 while ((ski = newKeys.pollFirst()) != null) { |
120 while ((ski = newKeys.pollFirst()) != null) { |
127 if (ski.isValid()) { |
121 if (ski.isValid()) { |
128 SelChImpl ch = ski.channel; |
122 int fd = ski.channel.getFDVal(); |
129 int fd = ch.getFDVal(); |
|
130 SelectionKeyImpl previous = fdToKey.put(fd, ski); |
123 SelectionKeyImpl previous = fdToKey.put(fd, ski); |
131 assert previous == null; |
124 assert previous == null; |
132 assert registered.get(fd) == false; |
125 assert ski.registeredEvents() == 0; |
133 } |
126 } |
134 } |
127 } |
135 |
128 |
136 // Translate the queued updates to changes to the set of monitored |
129 // Translate the queued updates to changes to the set of monitored |
137 // file descriptors. The changes are written to the /dev/poll driver |
130 // file descriptors. The changes are written to the /dev/poll driver |
138 // in bulk. |
131 // in bulk. |
139 assert updateKeys.size() == updateOps.size(); |
132 assert updateKeys.size() == updateEvents.size(); |
140 int index = 0; |
133 int index = 0; |
141 while ((ski = updateKeys.pollFirst()) != null) { |
134 while ((ski = updateKeys.pollFirst()) != null) { |
142 int ops = updateOps.pollFirst(); |
135 int newEvents = updateEvents.pollFirst(); |
143 int fd = ski.channel.getFDVal(); |
136 int fd = ski.channel.getFDVal(); |
144 if (ski.isValid() && fdToKey.containsKey(fd)) { |
137 if (ski.isValid() && fdToKey.containsKey(fd)) { |
145 if (registered.get(fd)) { |
138 int registeredEvents = ski.registeredEvents(); |
146 if (ops == 0) { |
139 if (newEvents != registeredEvents) { |
147 // remove file descriptor |
140 if (registeredEvents != 0) |
148 pollWrapper.putPollFD(index++, fd, POLLREMOVE); |
141 pollWrapper.putPollFD(index++, fd, POLLREMOVE); |
149 registered.clear(fd); |
142 if (newEvents != 0) |
150 } else { |
143 pollWrapper.putPollFD(index++, fd, (short)newEvents); |
151 // change events |
144 ski.registeredEvents(newEvents); |
152 pollWrapper.putPollFD(index++, fd, POLLREMOVE); |
145 |
153 pollWrapper.putPollFD(index++, fd, (short)ops); |
146 // write to /dev/poll |
|
147 if (index > (NUM_POLLFDS-2)) { |
|
148 pollWrapper.registerMultiple(index); |
|
149 index = 0; |
154 } |
150 } |
155 } else if (ops != 0) { |
|
156 // add file descriptor |
|
157 pollWrapper.putPollFD(index++, fd, (short)ops); |
|
158 registered.set(fd); |
|
159 } |
|
160 if (index > (NUM_POLLFDS-2)) { |
|
161 pollWrapper.registerMultiple(index); |
|
162 index = 0; |
|
163 } |
151 } |
164 } |
152 } |
165 } |
153 } |
166 |
154 |
167 // write any remaining changes |
155 // write any remaining changes |
169 pollWrapper.registerMultiple(index); |
157 pollWrapper.registerMultiple(index); |
170 } |
158 } |
171 } |
159 } |
172 |
160 |
173 /** |
161 /** |
174 * Update the keys whose fd's have been selected by the /dev/poll. |
162 * Update the keys of file descriptors that were polled and add them to |
175 * Add the ready keys to the ready queue. |
163 * the selected-key set. |
|
164 * If the interrupt fd has been selected, drain it and clear the interrupt. |
176 */ |
165 */ |
177 private int updateSelectedKeys(int numEntries) throws IOException { |
166 private int updateSelectedKeys(int numEntries) throws IOException { |
178 assert Thread.holdsLock(this); |
167 assert Thread.holdsLock(this); |
179 assert Thread.holdsLock(nioSelectedKeys()); |
168 assert Thread.holdsLock(nioSelectedKeys()); |
180 |
169 |
212 |
201 |
213 @Override |
202 @Override |
214 protected void implClose() throws IOException { |
203 protected void implClose() throws IOException { |
215 assert !isOpen(); |
204 assert !isOpen(); |
216 assert Thread.holdsLock(this); |
205 assert Thread.holdsLock(this); |
217 assert Thread.holdsLock(nioKeys()); |
|
218 |
206 |
219 // prevent further wakeup |
207 // prevent further wakeup |
220 synchronized (interruptLock) { |
208 synchronized (interruptLock) { |
221 interruptTriggered = true; |
209 interruptTriggered = true; |
222 } |
210 } |
223 |
211 |
224 pollWrapper.close(); |
212 pollWrapper.close(); |
225 FileDispatcherImpl.closeIntFD(fd0); |
213 FileDispatcherImpl.closeIntFD(fd0); |
226 FileDispatcherImpl.closeIntFD(fd1); |
214 FileDispatcherImpl.closeIntFD(fd1); |
227 |
|
228 // Deregister channels |
|
229 Iterator<SelectionKey> i = keys.iterator(); |
|
230 while (i.hasNext()) { |
|
231 SelectionKeyImpl ski = (SelectionKeyImpl)i.next(); |
|
232 deregister(ski); |
|
233 SelectableChannel selch = ski.channel(); |
|
234 if (!selch.isOpen() && !selch.isRegistered()) |
|
235 ((SelChImpl)selch).kill(); |
|
236 i.remove(); |
|
237 } |
|
238 } |
215 } |
239 |
216 |
240 @Override |
217 @Override |
241 protected void implRegister(SelectionKeyImpl ski) { |
218 protected void implRegister(SelectionKeyImpl ski) { |
242 assert Thread.holdsLock(nioKeys()); |
|
243 ensureOpen(); |
219 ensureOpen(); |
244 synchronized (updateLock) { |
220 synchronized (updateLock) { |
245 newKeys.addLast(ski); |
221 newKeys.addLast(ski); |
246 } |
222 } |
247 keys.add(ski); |
|
248 } |
223 } |
249 |
224 |
250 @Override |
225 @Override |
251 protected void implDereg(SelectionKeyImpl ski) throws IOException { |
226 protected void implDereg(SelectionKeyImpl ski) throws IOException { |
252 assert !ski.isValid(); |
227 assert !ski.isValid(); |
253 assert Thread.holdsLock(this); |
228 assert Thread.holdsLock(this); |
254 assert Thread.holdsLock(nioKeys()); |
|
255 assert Thread.holdsLock(nioSelectedKeys()); |
|
256 |
229 |
257 int fd = ski.channel.getFDVal(); |
230 int fd = ski.channel.getFDVal(); |
258 fdToKey.remove(fd); |
231 if (fdToKey.remove(fd) != null) { |
259 if (registered.get(fd)) { |
232 if (ski.registeredEvents() != 0) { |
260 pollWrapper.register(fd, POLLREMOVE); |
233 pollWrapper.register(fd, POLLREMOVE); |
261 registered.clear(fd); |
234 ski.registeredEvents(0); |
262 } |
235 } |
263 |
236 } else { |
264 selectedKeys.remove(ski); |
237 assert ski.registeredEvents() == 0; |
265 keys.remove(ski); |
238 } |
266 |
239 } |
267 // remove from channel's key set |
240 |
268 deregister(ski); |
241 @Override |
269 |
242 public void putEventOps(SelectionKeyImpl ski, int events) { |
270 SelectableChannel selch = ski.channel(); |
|
271 if (!selch.isOpen() && !selch.isRegistered()) |
|
272 ((SelChImpl) selch).kill(); |
|
273 } |
|
274 |
|
275 @Override |
|
276 public void putEventOps(SelectionKeyImpl ski, int ops) { |
|
277 ensureOpen(); |
243 ensureOpen(); |
278 synchronized (updateLock) { |
244 synchronized (updateLock) { |
279 updateOps.addLast(ops); // ops first in case adding the key fails |
245 updateEvents.addLast(events); // events first in case adding key fails |
280 updateKeys.addLast(ski); |
246 updateKeys.addLast(ski); |
281 } |
247 } |
282 } |
248 } |
283 |
249 |
284 @Override |
250 @Override |