71 * channel then that operation will immediately return, either by throwing an
72 * exception or by returning normally. If a thread is interrupted or the
73 * channel upon which it is blocked is asynchronously closed then the channel's
74 * {@link #end end} method will throw the appropriate exception.
75 *
76 * <p> This class performs the synchronization required to implement the {@link
77 * java.nio.channels.Channel} specification. Implementations of the {@link
78 * #implCloseChannel implCloseChannel} method need not synchronize against
79 * other threads that might be attempting to close the channel. </p>
80 *
81 *
82 * @author Mark Reinhold
83 * @author JSR-51 Expert Group
84 * @since 1.4
85 */
86
87 public abstract class AbstractInterruptibleChannel
88 implements Channel, InterruptibleChannel
89 {
90
91 private Object closeLock = new Object();
92 private volatile boolean open = true;
93
94 /**
95 * Initializes a new instance of this class.
96 */
97 protected AbstractInterruptibleChannel() { }
98
99 /**
100 * Closes this channel.
101 *
102 * <p> If the channel has already been closed then this method returns
103 * immediately. Otherwise it marks the channel as closed and then invokes
104 * the {@link #implCloseChannel implCloseChannel} method in order to
105 * complete the close operation. </p>
106 *
107 * @throws IOException
108 * If an I/O error occurs
109 */
110 public final void close() throws IOException {
111 synchronized (closeLock) {
125 * more than once.
126 *
127 * <p> An implementation of this method must arrange for any other thread
128 * that is blocked in an I/O operation upon this channel to return
129 * immediately, either by throwing an exception or by returning normally.
130 * </p>
131 *
132 * @throws IOException
133 * If an I/O error occurs while closing the channel
134 */
135 protected abstract void implCloseChannel() throws IOException;
136
137 public final boolean isOpen() {
138 return open;
139 }
140
141
142 // -- Interruption machinery --
143
144 private Interruptible interruptor;
145 private volatile boolean interrupted = false;
146
147 /**
148 * Marks the beginning of an I/O operation that might block indefinitely.
149 *
150 * <p> This method should be invoked in tandem with the {@link #end end}
151 * method, using a <tt>try</tt> ... <tt>finally</tt> block as
152 * shown <a href="#be">above</a>, in order to implement asynchronous
153 * closing and interruption for this channel. </p>
154 */
155 protected final void begin() {
156 if (interruptor == null) {
157 interruptor = new Interruptible() {
158 public void interrupt() {
159 synchronized (closeLock) {
160 if (!open)
161 return;
162 interrupted = true;
163 open = false;
164 try {
165 AbstractInterruptibleChannel.this.implCloseChannel();
166 } catch (IOException x) { }
167 }
168 }};
169 }
170 blockedOn(interruptor);
171 if (Thread.currentThread().isInterrupted())
172 interruptor.interrupt();
173 }
174
175 /**
176 * Marks the end of an I/O operation that might block indefinitely.
177 *
178 * <p> This method should be invoked in tandem with the {@link #begin
179 * begin} method, using a <tt>try</tt> ... <tt>finally</tt> block
180 * as shown <a href="#be">above</a>, in order to implement asynchronous
181 * closing and interruption for this channel. </p>
182 *
183 * @param completed
184 * <tt>true</tt> if, and only if, the I/O operation completed
185 * successfully, that is, had some effect that would be visible to
186 * the operation's invoker
187 *
188 * @throws AsynchronousCloseException
189 * If the channel was asynchronously closed
190 *
191 * @throws ClosedByInterruptException
192 * If the thread blocked in the I/O operation was interrupted
193 */
194 protected final void end(boolean completed)
195 throws AsynchronousCloseException
196 {
197 blockedOn(null);
198 if (completed) {
199 interrupted = false;
200 return;
201 }
202 if (interrupted) throw new ClosedByInterruptException();
203 if (!open) throw new AsynchronousCloseException();
204 }
205
206
207 // -- sun.misc.SharedSecrets --
208 static void blockedOn(Interruptible intr) { // package-private
209 sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(),
210 intr);
211 }
212 }
|
71 * channel then that operation will immediately return, either by throwing an
72 * exception or by returning normally. If a thread is interrupted or the
73 * channel upon which it is blocked is asynchronously closed then the channel's
74 * {@link #end end} method will throw the appropriate exception.
75 *
76 * <p> This class performs the synchronization required to implement the {@link
77 * java.nio.channels.Channel} specification. Implementations of the {@link
78 * #implCloseChannel implCloseChannel} method need not synchronize against
79 * other threads that might be attempting to close the channel. </p>
80 *
81 *
82 * @author Mark Reinhold
83 * @author JSR-51 Expert Group
84 * @since 1.4
85 */
86
87 public abstract class AbstractInterruptibleChannel
88 implements Channel, InterruptibleChannel
89 {
90
91 private final Object closeLock = new Object();
92 private volatile boolean open = true;
93
94 /**
95 * Initializes a new instance of this class.
96 */
97 protected AbstractInterruptibleChannel() { }
98
99 /**
100 * Closes this channel.
101 *
102 * <p> If the channel has already been closed then this method returns
103 * immediately. Otherwise it marks the channel as closed and then invokes
104 * the {@link #implCloseChannel implCloseChannel} method in order to
105 * complete the close operation. </p>
106 *
107 * @throws IOException
108 * If an I/O error occurs
109 */
110 public final void close() throws IOException {
111 synchronized (closeLock) {
125 * more than once.
126 *
127 * <p> An implementation of this method must arrange for any other thread
128 * that is blocked in an I/O operation upon this channel to return
129 * immediately, either by throwing an exception or by returning normally.
130 * </p>
131 *
132 * @throws IOException
133 * If an I/O error occurs while closing the channel
134 */
135 protected abstract void implCloseChannel() throws IOException;
136
137 public final boolean isOpen() {
138 return open;
139 }
140
141
142 // -- Interruption machinery --
143
144 private Interruptible interruptor;
145 private volatile Thread interrupted;
146
147 /**
148 * Marks the beginning of an I/O operation that might block indefinitely.
149 *
150 * <p> This method should be invoked in tandem with the {@link #end end}
151 * method, using a <tt>try</tt> ... <tt>finally</tt> block as
152 * shown <a href="#be">above</a>, in order to implement asynchronous
153 * closing and interruption for this channel. </p>
154 */
155 protected final void begin() {
156 if (interruptor == null) {
157 interruptor = new Interruptible() {
158 public void interrupt(Thread target) {
159 synchronized (closeLock) {
160 if (!open)
161 return;
162 open = false;
163 interrupted = target;
164 try {
165 AbstractInterruptibleChannel.this.implCloseChannel();
166 } catch (IOException x) { }
167 }
168 }};
169 }
170 blockedOn(interruptor);
171 Thread me = Thread.currentThread();
172 if (me.isInterrupted())
173 interruptor.interrupt(me);
174 }
175
176 /**
177 * Marks the end of an I/O operation that might block indefinitely.
178 *
179 * <p> This method should be invoked in tandem with the {@link #begin
180 * begin} method, using a <tt>try</tt> ... <tt>finally</tt> block
181 * as shown <a href="#be">above</a>, in order to implement asynchronous
182 * closing and interruption for this channel. </p>
183 *
184 * @param completed
185 * <tt>true</tt> if, and only if, the I/O operation completed
186 * successfully, that is, had some effect that would be visible to
187 * the operation's invoker
188 *
189 * @throws AsynchronousCloseException
190 * If the channel was asynchronously closed
191 *
192 * @throws ClosedByInterruptException
193 * If the thread blocked in the I/O operation was interrupted
194 */
195 protected final void end(boolean completed)
196 throws AsynchronousCloseException
197 {
198 blockedOn(null);
199 Thread interrupted = this.interrupted;
200 if (interrupted != null && interrupted == Thread.currentThread()) {
201 interrupted = null;
202 throw new ClosedByInterruptException();
203 }
204 if (!completed && !open)
205 throw new AsynchronousCloseException();
206 }
207
208
209 // -- sun.misc.SharedSecrets --
210 static void blockedOn(Interruptible intr) { // package-private
211 sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(),
212 intr);
213 }
214 }
|