1 /*
2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 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 java.nio.channels.spi;
27
28 import java.io.IOException;
29 import java.nio.channels.*;
30
31
32 /**
33 * Base implementation class for selectable channels.
34 *
35 * <p> This class defines methods that handle the mechanics of channel
36 * registration, deregistration, and closing. It maintains the current
37 * blocking mode of this channel as well as its current set of selection keys.
38 * It performs all of the synchronization required to implement the {@link
39 * java.nio.channels.SelectableChannel} specification. Implementations of the
40 * abstract protected methods defined in this class need not synchronize
41 * against other threads that might be engaged in the same operations. </p>
42 *
43 *
44 * @author Mark Reinhold
45 * @author Mike McCloskey
46 * @author JSR-51 Expert Group
47 * @since 1.4
48 */
49
50 public abstract class AbstractSelectableChannel
51 extends SelectableChannel
52 {
53
54 // The provider that created this channel
55 private final SelectorProvider provider;
56
57 // Keys that have been created by registering this channel with selectors.
58 // They are saved because if this channel is closed the keys must be
59 // deregistered. Protected by keyLock.
60 //
61 private SelectionKey[] keys = null;
62 private int keyCount = 0;
63
64 // Lock for key set and count
65 private final Object keyLock = new Object();
66
67 // Lock for registration and configureBlocking operations
68 private final Object regLock = new Object();
69
70 // Blocking mode, protected by regLock
71 boolean blocking = true;
72
73 /**
74 * Initializes a new instance of this class.
75 *
76 * @param provider
77 * The provider that created this channel
78 */
79 protected AbstractSelectableChannel(SelectorProvider provider) {
80 this.provider = provider;
81 }
82
83 /**
84 * Returns the provider that created this channel.
85 *
86 * @return The provider that created this channel
87 */
88 public final SelectorProvider provider() {
89 return provider;
90 }
91
180 *
181 * @throws ClosedSelectorException {@inheritDoc}
182 *
183 * @throws IllegalBlockingModeException {@inheritDoc}
184 *
185 * @throws IllegalSelectorException {@inheritDoc}
186 *
187 * @throws CancelledKeyException {@inheritDoc}
188 *
189 * @throws IllegalArgumentException {@inheritDoc}
190 */
191 public final SelectionKey register(Selector sel, int ops,
192 Object att)
193 throws ClosedChannelException
194 {
195 synchronized (regLock) {
196 if (!isOpen())
197 throw new ClosedChannelException();
198 if ((ops & ~validOps()) != 0)
199 throw new IllegalArgumentException();
200 if (blocking)
201 throw new IllegalBlockingModeException();
202 SelectionKey k = findKey(sel);
203 if (k != null) {
204 k.interestOps(ops);
205 k.attach(att);
206 }
207 if (k == null) {
208 // New registration
209 synchronized (keyLock) {
210 if (!isOpen())
211 throw new ClosedChannelException();
212 k = ((AbstractSelector)sel).register(this, ops, att);
213 addKey(k);
214 }
215 }
216 return k;
217 }
218 }
219
220
247 *
248 * <p> This method is invoked by the {@link java.nio.channels.Channel#close
249 * close} method in order to perform the actual work of closing the
250 * channel. This method is only invoked if the channel has not yet been
251 * closed, and it is never invoked more than once.
252 *
253 * <p> An implementation of this method must arrange for any other thread
254 * that is blocked in an I/O operation upon this channel to return
255 * immediately, either by throwing an exception or by returning normally.
256 * </p>
257 *
258 * @throws IOException
259 * If an I/O error occurs
260 */
261 protected abstract void implCloseSelectableChannel() throws IOException;
262
263
264 // -- Blocking --
265
266 public final boolean isBlocking() {
267 synchronized (regLock) {
268 return blocking;
269 }
270 }
271
272 public final Object blockingLock() {
273 return regLock;
274 }
275
276 /**
277 * Adjusts this channel's blocking mode.
278 *
279 * <p> If the given blocking mode is different from the current blocking
280 * mode then this method invokes the {@link #implConfigureBlocking
281 * implConfigureBlocking} method, while holding the appropriate locks, in
282 * order to change the mode. </p>
283 */
284 public final SelectableChannel configureBlocking(boolean block)
285 throws IOException
286 {
287 synchronized (regLock) {
288 if (!isOpen())
289 throw new ClosedChannelException();
290 if (blocking == block)
291 return this;
292 if (block && haveValidKeys())
293 throw new IllegalBlockingModeException();
294 implConfigureBlocking(block);
295 blocking = block;
296 }
297 return this;
298 }
299
300 /**
301 * Adjusts this channel's blocking mode.
302 *
303 * <p> This method is invoked by the {@link #configureBlocking
304 * configureBlocking} method in order to perform the actual work of
305 * changing the blocking mode. This method is only invoked if the new mode
306 * is different from the current mode. </p>
307 *
308 * @param block If {@code true} then this channel will be placed in
309 * blocking mode; if {@code false} then it will be placed
310 * non-blocking mode
311 *
312 * @throws IOException
313 * If an I/O error occurs
314 */
315 protected abstract void implConfigureBlocking(boolean block)
|
1 /*
2 * Copyright (c) 2000, 2018, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 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 java.nio.channels.spi;
27
28 import java.io.IOException;
29 import java.nio.channels.CancelledKeyException;
30 import java.nio.channels.ClosedChannelException;
31 import java.nio.channels.ClosedSelectorException;
32 import java.nio.channels.IllegalBlockingModeException;
33 import java.nio.channels.IllegalSelectorException;
34 import java.nio.channels.SelectableChannel;
35 import java.nio.channels.SelectionKey;
36 import java.nio.channels.Selector;
37
38
39 /**
40 * Base implementation class for selectable channels.
41 *
42 * <p> This class defines methods that handle the mechanics of channel
43 * registration, deregistration, and closing. It maintains the current
44 * blocking mode of this channel as well as its current set of selection keys.
45 * It performs all of the synchronization required to implement the {@link
46 * java.nio.channels.SelectableChannel} specification. Implementations of the
47 * abstract protected methods defined in this class need not synchronize
48 * against other threads that might be engaged in the same operations. </p>
49 *
50 *
51 * @author Mark Reinhold
52 * @author Mike McCloskey
53 * @author JSR-51 Expert Group
54 * @since 1.4
55 */
56
57 public abstract class AbstractSelectableChannel
58 extends SelectableChannel
59 {
60
61 // The provider that created this channel
62 private final SelectorProvider provider;
63
64 // Keys that have been created by registering this channel with selectors.
65 // They are saved because if this channel is closed the keys must be
66 // deregistered. Protected by keyLock.
67 //
68 private SelectionKey[] keys = null;
69 private int keyCount = 0;
70
71 // Lock for key set and count
72 private final Object keyLock = new Object();
73
74 // Lock for registration and configureBlocking operations
75 private final Object regLock = new Object();
76
77 // Blocking mode, need regLock to change;
78 private volatile boolean nonBlocking;
79
80 /**
81 * Initializes a new instance of this class.
82 *
83 * @param provider
84 * The provider that created this channel
85 */
86 protected AbstractSelectableChannel(SelectorProvider provider) {
87 this.provider = provider;
88 }
89
90 /**
91 * Returns the provider that created this channel.
92 *
93 * @return The provider that created this channel
94 */
95 public final SelectorProvider provider() {
96 return provider;
97 }
98
187 *
188 * @throws ClosedSelectorException {@inheritDoc}
189 *
190 * @throws IllegalBlockingModeException {@inheritDoc}
191 *
192 * @throws IllegalSelectorException {@inheritDoc}
193 *
194 * @throws CancelledKeyException {@inheritDoc}
195 *
196 * @throws IllegalArgumentException {@inheritDoc}
197 */
198 public final SelectionKey register(Selector sel, int ops,
199 Object att)
200 throws ClosedChannelException
201 {
202 synchronized (regLock) {
203 if (!isOpen())
204 throw new ClosedChannelException();
205 if ((ops & ~validOps()) != 0)
206 throw new IllegalArgumentException();
207 if (isBlocking())
208 throw new IllegalBlockingModeException();
209 SelectionKey k = findKey(sel);
210 if (k != null) {
211 k.interestOps(ops);
212 k.attach(att);
213 }
214 if (k == null) {
215 // New registration
216 synchronized (keyLock) {
217 if (!isOpen())
218 throw new ClosedChannelException();
219 k = ((AbstractSelector)sel).register(this, ops, att);
220 addKey(k);
221 }
222 }
223 return k;
224 }
225 }
226
227
254 *
255 * <p> This method is invoked by the {@link java.nio.channels.Channel#close
256 * close} method in order to perform the actual work of closing the
257 * channel. This method is only invoked if the channel has not yet been
258 * closed, and it is never invoked more than once.
259 *
260 * <p> An implementation of this method must arrange for any other thread
261 * that is blocked in an I/O operation upon this channel to return
262 * immediately, either by throwing an exception or by returning normally.
263 * </p>
264 *
265 * @throws IOException
266 * If an I/O error occurs
267 */
268 protected abstract void implCloseSelectableChannel() throws IOException;
269
270
271 // -- Blocking --
272
273 public final boolean isBlocking() {
274 return !nonBlocking;
275 }
276
277 public final Object blockingLock() {
278 return regLock;
279 }
280
281 /**
282 * Adjusts this channel's blocking mode.
283 *
284 * <p> If the given blocking mode is different from the current blocking
285 * mode then this method invokes the {@link #implConfigureBlocking
286 * implConfigureBlocking} method, while holding the appropriate locks, in
287 * order to change the mode. </p>
288 */
289 public final SelectableChannel configureBlocking(boolean block)
290 throws IOException
291 {
292 synchronized (regLock) {
293 if (!isOpen())
294 throw new ClosedChannelException();
295 boolean blocking = !nonBlocking;
296 if (block != blocking) {
297 if (block && haveValidKeys())
298 throw new IllegalBlockingModeException();
299 implConfigureBlocking(block);
300 nonBlocking = !block;
301 }
302 }
303 return this;
304 }
305
306 /**
307 * Adjusts this channel's blocking mode.
308 *
309 * <p> This method is invoked by the {@link #configureBlocking
310 * configureBlocking} method in order to perform the actual work of
311 * changing the blocking mode. This method is only invoked if the new mode
312 * is different from the current mode. </p>
313 *
314 * @param block If {@code true} then this channel will be placed in
315 * blocking mode; if {@code false} then it will be placed
316 * non-blocking mode
317 *
318 * @throws IOException
319 * If an I/O error occurs
320 */
321 protected abstract void implConfigureBlocking(boolean block)
|