KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > nio > channels > spi > AbstractInterruptibleChannel


1 /*
2  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
3  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4  */

5
6 /*
7  * @(#)AbstractInterruptibleChannel.java 1.16 06/03/22
8  */

9
10 package java.nio.channels.spi;
11
12 import java.io.IOException JavaDoc;
13 import java.lang.reflect.Method JavaDoc;
14 import java.lang.reflect.InvocationTargetException JavaDoc;
15 import java.nio.channels.*;
16 import java.security.AccessController JavaDoc;
17 import java.security.PrivilegedAction JavaDoc;
18 import sun.nio.ch.Interruptible;
19
20
21 /**
22  * Base implementation class for interruptible channels.
23  *
24  * <p> This class encapsulates the low-level machinery required to implement
25  * the asynchronous closing and interruption of channels. A concrete channel
26  * class must invoke the {@link #begin begin} and {@link #end end} methods
27  * before and after, respectively, invoking an I/O operation that might block
28  * indefinitely. In order to ensure that the {@link #end end} method is always
29  * invoked, these methods should be used within a
30  * <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block: <a name="be">
31  *
32  * <blockquote><pre>
33  * boolean completed = false;
34  * try {
35  * begin();
36  * completed = ...; // Perform blocking I/O operation
37  * return ...; // Return result
38  * } finally {
39  * end(completed);
40  * }</pre></blockquote>
41  *
42  * <p> The <tt>completed</tt> argument to the {@link #end end} method tells
43  * whether or not the I/O operation actually completed, that is, whether it had
44  * any effect that would be visible to the invoker. In the case of an
45  * operation that reads bytes, for example, this argument should be
46  * <tt>true</tt> if, and only if, some bytes were actually transferred into the
47  * invoker's target buffer.
48  *
49  * <p> A concrete channel class must also implement the {@link
50  * #implCloseChannel implCloseChannel} method in such a way that if it is
51  * invoked while another thread is blocked in a native I/O operation upon the
52  * channel then that operation will immediately return, either by throwing an
53  * exception or by returning normally. If a thread is interrupted or the
54  * channel upon which it is blocked is asynchronously closed then the channel's
55  * {@link #end end} method will throw the appropriate exception.
56  *
57  * <p> This class performs the synchronization required to implement the {@link
58  * java.nio.channels.Channel} specification. Implementations of the {@link
59  * #implCloseChannel implCloseChannel} method need not synchronize against
60  * other threads that might be attempting to close the channel. </p>
61  *
62  *
63  * @author Mark Reinhold
64  * @author JSR-51 Expert Group
65  * @version 1.16, 06/03/22
66  * @since 1.4
67  */

68
69 public abstract class AbstractInterruptibleChannel
70     implements Channel, InterruptibleChannel
71 {
72
73     private Object JavaDoc closeLock = new Object JavaDoc();
74     private volatile boolean open = true;
75
76     /**
77      * Initializes a new instance of this class.
78      */

79     protected AbstractInterruptibleChannel() { }
80
81     /**
82      * Closes this channel.
83      *
84      * <p> If the channel has already been closed then this method returns
85      * immediately. Otherwise it marks the channel as closed and then invokes
86      * the {@link #implCloseChannel implCloseChannel} method in order to
87      * complete the close operation. </p>
88      *
89      * @throws IOException
90      * If an I/O error occurs
91      */

92     public final void close() throws IOException JavaDoc {
93     synchronized (closeLock) {
94         if (!open)
95         return;
96         open = false;
97         implCloseChannel();
98     }
99     }
100
101     /**
102      * Closes this channel.
103      *
104      * <p> This method is invoked by the {@link #close close} method in order
105      * to perform the actual work of closing the channel. This method is only
106      * invoked if the channel has not yet been closed, and it is never invoked
107      * more than once.
108      *
109      * <p> An implementation of this method must arrange for any other thread
110      * that is blocked in an I/O operation upon this channel to return
111      * immediately, either by throwing an exception or by returning normally.
112      * </p>
113      *
114      * @throws IOException
115      * If an I/O error occurs while closing the channel
116      */

117     protected abstract void implCloseChannel() throws IOException JavaDoc;
118
119     public final boolean isOpen() {
120     return open;
121     }
122
123
124     // -- Interruption machinery --
125

126     private Interruptible interruptor;
127     private volatile boolean interrupted = false;
128
129     /**
130      * Marks the beginning of an I/O operation that might block indefinitely.
131      *
132      * <p> This method should be invoked in tandem with the {@link #end end}
133      * method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block as
134      * shown <a HREF="#be">above</a>, in order to implement asynchronous
135      * closing and interruption for this channel. </p>
136      */

137     protected final void begin() {
138     if (interruptor == null) {
139         interruptor = new Interruptible() {
140             public void interrupt() {
141             synchronized (closeLock) {
142                 if (!open)
143                 return;
144                 interrupted = true;
145                 open = false;
146                 try {
147                 AbstractInterruptibleChannel.this.implCloseChannel();
148                 } catch (IOException JavaDoc x) { }
149             }
150             }};
151     }
152     blockedOn(interruptor);
153     if (Thread.currentThread().isInterrupted())
154         interruptor.interrupt();
155     }
156
157     /**
158      * Marks the end of an I/O operation that might block indefinitely.
159      *
160      * <p> This method should be invoked in tandem with the {@link #begin
161      * begin} method, using a <tt>try</tt>&nbsp;...&nbsp;<tt>finally</tt> block
162      * as shown <a HREF="#be">above</a>, in order to implement asynchronous
163      * closing and interruption for this channel. </p>
164      *
165      * @param completed
166      * <tt>true</tt> if, and only if, the I/O operation completed
167      * successfully, that is, had some effect that would be visible to
168      * the operation's invoker
169      *
170      * @throws AsynchronousCloseException
171      * If the channel was asynchronously closed
172      *
173      * @throws ClosedByInterruptException
174      * If the thread blocked in the I/O operation was interrupted
175      */

176     protected final void end(boolean completed)
177     throws AsynchronousCloseException
178     {
179     blockedOn(null);
180     if (completed) {
181         interrupted = false;
182         return;
183     }
184     if (interrupted) throw new ClosedByInterruptException();
185     if (!open) throw new AsynchronousCloseException();
186     }
187
188
189     // -- sun.misc.SharedSecrets --
190
static void blockedOn(Interruptible intr) { // package-private
191
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(),
192                                  intr);
193     }
194 }
195
Popular Tags