2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package java.nio.channels.spi;
20 import java.io.IOException;
21 import java.lang.reflect.Method;
22 import java.nio.channels.AsynchronousCloseException;
23 import java.nio.channels.Channel;
24 import java.nio.channels.ClosedByInterruptException;
25 import java.nio.channels.InterruptibleChannel;
26 import java.security.AccessController;
27 import java.security.PrivilegedActionException;
28 import java.security.PrivilegedExceptionAction;
31 * {@code AbstractInterruptibleChannel} is the root class for interruptible
34 * The basic usage pattern for an interruptible channel is to invoke
35 * {@code begin()} before any I/O operation that potentially blocks
36 * indefinitely, then {@code end(boolean)} after completing the operation. The
37 * argument to the {@code end} method should indicate if the I/O operation has
38 * actually completed so that any change may be visible to the invoker.
40 public abstract class AbstractInterruptibleChannel implements Channel,
41 InterruptibleChannel {
43 static Method setInterruptAction = null;
47 setInterruptAction = AccessController
48 .doPrivileged(new PrivilegedExceptionAction<Method>() {
49 public Method run() throws Exception {
50 return Thread.class.getDeclaredMethod(
52 new Class[] { Runnable.class });
56 setInterruptAction.setAccessible(true);
57 } catch (PrivilegedActionException e) {
58 // FIXME: be accommodate before VM actually provides
59 // setInterruptAction method
60 // throw new Error(e);
64 private volatile boolean closed = false;
66 volatile boolean interrupted = false;
69 * Default constructor.
71 protected AbstractInterruptibleChannel() {
76 * Indicates whether this channel is open.
78 * @return {@code true} if this channel is open, {@code false} if it is
80 * @see java.nio.channels.Channel#isOpen()
82 public synchronized final boolean isOpen() {
87 * Closes an open channel. If the channel is already closed then this method
88 * has no effect, otherwise it closes the receiver via the
89 * {@code implCloseChannel} method.
91 * If an attempt is made to perform an operation on a closed channel then a
92 * {@link java.nio.channels.ClosedChannelException} is thrown.
94 * If multiple threads attempt to simultaneously close a channel, then only
95 * one thread will run the closure code and the others will be blocked until
96 * the first one completes.
99 * if a problem occurs while closing this channel.
100 * @see java.nio.channels.Channel#close()
102 public final void close() throws IOException {
104 synchronized (this) {
114 * Indicates the beginning of a code section that includes an I/O operation
115 * that is potentially blocking. After this operation, the application
116 * should invoke the corresponding {@code end(boolean)} method.
118 protected final void begin() {
119 // FIXME: be accommodate before VM actually provides
120 // setInterruptAction method
121 if (setInterruptAction != null) {
123 setInterruptAction.invoke(Thread.currentThread(),
124 new Object[] { new Runnable() {
128 AbstractInterruptibleChannel.this.close();
129 } catch (IOException e) {
134 } catch (Exception e) {
135 throw new RuntimeException(e);
141 * Indicates the end of a code section that has been started with
142 * {@code begin()} and that includes a potentially blocking I/O operation.
145 * pass {@code true} if the blocking operation has succeeded and
146 * has had a noticeable effect; {@code false} otherwise.
147 * @throws AsynchronousCloseException
148 * if this channel is closed by another thread while this method
150 * @throws ClosedByInterruptException
151 * if another thread interrupts the calling thread while this
152 * method is executing.
154 protected final void end(boolean success) throws AsynchronousCloseException {
155 // FIXME: be accommodate before VM actually provides
156 // setInterruptAction method
157 if (setInterruptAction != null) {
159 setInterruptAction.invoke(Thread.currentThread(),
160 new Object[] { null });
161 } catch (Exception e) {
162 throw new RuntimeException(e);
166 throw new ClosedByInterruptException();
169 if (!success && closed) {
170 throw new AsynchronousCloseException();
175 * Implements the channel closing behavior.
177 * Closes the channel with a guarantee that the channel is not currently
178 * closed through another invocation of {@code close()} and that the method
181 * Any outstanding threads blocked on I/O operations on this channel must be
182 * released with either a normal return code, or by throwing an
183 * {@code AsynchronousCloseException}.
185 * @throws IOException
186 * if a problem occurs while closing the channel.
188 protected abstract void implCloseChannel() throws IOException;