106 // Find empty element of key array |
106 // Find empty element of key array |
107 for (i = 0; i < keys.length; i++) |
107 for (i = 0; i < keys.length; i++) |
108 if (keys[i] == null) |
108 if (keys[i] == null) |
109 break; |
109 break; |
110 } else if (keys == null) { |
110 } else if (keys == null) { |
111 keys = new SelectionKey[3]; |
111 keys = new SelectionKey[2]; |
112 } else { |
112 } else { |
113 // Grow key array |
113 // Grow key array |
114 int n = keys.length * 2; |
114 int n = keys.length * 2; |
115 SelectionKey[] ks = new SelectionKey[n]; |
115 SelectionKey[] ks = new SelectionKey[n]; |
116 for (i = 0; i < keys.length; i++) |
116 for (i = 0; i < keys.length; i++) |
121 keys[i] = k; |
121 keys[i] = k; |
122 keyCount++; |
122 keyCount++; |
123 } |
123 } |
124 |
124 |
125 private SelectionKey findKey(Selector sel) { |
125 private SelectionKey findKey(Selector sel) { |
126 synchronized (keyLock) { |
126 assert Thread.holdsLock(keyLock); |
127 if (keys == null) |
127 if (keys == null) |
128 return null; |
|
129 for (int i = 0; i < keys.length; i++) |
|
130 if ((keys[i] != null) && (keys[i].selector() == sel)) |
|
131 return keys[i]; |
|
132 return null; |
128 return null; |
133 } |
129 for (int i = 0; i < keys.length; i++) |
|
130 if ((keys[i] != null) && (keys[i].selector() == sel)) |
|
131 return keys[i]; |
|
132 return null; |
|
133 |
134 } |
134 } |
135 |
135 |
136 void removeKey(SelectionKey k) { // package-private |
136 void removeKey(SelectionKey k) { // package-private |
137 synchronized (keyLock) { |
137 synchronized (keyLock) { |
138 for (int i = 0; i < keys.length; i++) |
138 for (int i = 0; i < keys.length; i++) |
193 * |
195 * |
194 * @throws CancelledKeyException {@inheritDoc} |
196 * @throws CancelledKeyException {@inheritDoc} |
195 * |
197 * |
196 * @throws IllegalArgumentException {@inheritDoc} |
198 * @throws IllegalArgumentException {@inheritDoc} |
197 */ |
199 */ |
198 public final SelectionKey register(Selector sel, int ops, |
200 public final SelectionKey register(Selector sel, int ops, Object att) |
199 Object att) |
|
200 throws ClosedChannelException |
201 throws ClosedChannelException |
201 { |
202 { |
|
203 if ((ops & ~validOps()) != 0) |
|
204 throw new IllegalArgumentException(); |
|
205 if (!isOpen()) |
|
206 throw new ClosedChannelException(); |
202 synchronized (regLock) { |
207 synchronized (regLock) { |
203 if (!isOpen()) |
|
204 throw new ClosedChannelException(); |
|
205 if ((ops & ~validOps()) != 0) |
|
206 throw new IllegalArgumentException(); |
|
207 if (isBlocking()) |
208 if (isBlocking()) |
208 throw new IllegalBlockingModeException(); |
209 throw new IllegalBlockingModeException(); |
209 SelectionKey k = findKey(sel); |
210 synchronized (keyLock) { |
210 if (k != null) { |
211 // re-check if channel has been closed |
211 k.interestOps(ops); |
212 if (!isOpen()) |
212 k.attach(att); |
213 throw new ClosedChannelException(); |
213 } |
214 SelectionKey k = findKey(sel); |
214 if (k == null) { |
215 if (k != null) { |
215 // New registration |
216 k.attach(att); |
216 synchronized (keyLock) { |
217 k.interestOps(ops); |
217 if (!isOpen()) |
218 } else { |
218 throw new ClosedChannelException(); |
219 // New registration |
219 k = ((AbstractSelector)sel).register(this, ops, att); |
220 k = ((AbstractSelector)sel).register(this, ops, att); |
220 addKey(k); |
221 addKey(k); |
221 } |
222 } |
222 } |
223 return k; |
223 return k; |
224 } |
224 } |
225 } |
225 } |
226 } |
226 |
227 |
227 |
228 |
228 // -- Closing -- |
229 // -- Closing -- |
237 * order to perform the actual work of closing this channel. It then |
238 * order to perform the actual work of closing this channel. It then |
238 * cancels all of this channel's keys. </p> |
239 * cancels all of this channel's keys. </p> |
239 */ |
240 */ |
240 protected final void implCloseChannel() throws IOException { |
241 protected final void implCloseChannel() throws IOException { |
241 implCloseSelectableChannel(); |
242 implCloseSelectableChannel(); |
242 synchronized (keyLock) { |
243 |
243 int count = (keys == null) ? 0 : keys.length; |
244 // clone keys to avoid calling cancel when holding keyLock |
244 for (int i = 0; i < count; i++) { |
245 SelectionKey[] copyOfKeys = null; |
245 SelectionKey k = keys[i]; |
246 synchronized (keyLock) { |
246 if (k != null) |
247 if (keys != null) { |
247 k.cancel(); |
248 copyOfKeys = keys.clone(); |
|
249 } |
|
250 } |
|
251 |
|
252 if (copyOfKeys != null) { |
|
253 for (SelectionKey k : copyOfKeys) { |
|
254 if (k != null) { |
|
255 k.cancel(); // invalidate and adds key to cancelledKey set |
|
256 } |
248 } |
257 } |
249 } |
258 } |
250 } |
259 } |
251 |
260 |
252 /** |
261 /** |