36 public class PipedReader extends Reader {
37 boolean closedByWriter = false;
38 boolean closedByReader = false;
39 boolean connected = false;
40
41 /* REMIND: identification of the read and write sides needs to be
42 more sophisticated. Either using thread groups (but what about
43 pipes within a thread?) or using finalization (but it may be a
44 long time until the next GC). */
45 Thread readSide;
46 Thread writeSide;
47
48 /**
49 * The size of the pipe's circular input buffer.
50 */
51 private static final int DEFAULT_PIPE_SIZE = 1024;
52
53 /**
54 * The circular buffer into which incoming data is placed.
55 */
56 char buffer[];
57
58 /**
59 * The index of the position in the circular buffer at which the
60 * next character of data will be stored when received from the connected
61 * piped writer. <code>in<0</code> implies the buffer is empty,
62 * <code>in==out</code> implies the buffer is full
63 */
64 int in = -1;
65
66 /**
67 * The index of the position in the circular buffer at which the next
68 * character of data will be read by this piped reader.
69 */
70 int out = 0;
71
72 /**
73 * Creates a <code>PipedReader</code> so
74 * that it is connected to the piped writer
75 * <code>src</code>. Data written to <code>src</code>
76 * will then be available as input from this stream.
184 try {
185 wait(1000);
186 } catch (InterruptedException ex) {
187 throw new java.io.InterruptedIOException();
188 }
189 }
190 if (in < 0) {
191 in = 0;
192 out = 0;
193 }
194 buffer[in++] = (char) c;
195 if (in >= buffer.length) {
196 in = 0;
197 }
198 }
199
200 /**
201 * Receives data into an array of characters. This method will
202 * block until some input is available.
203 */
204 synchronized void receive(char c[], int off, int len) throws IOException {
205 while (--len >= 0) {
206 receive(c[off++]);
207 }
208 }
209
210 /**
211 * Notifies all waiting threads that the last character of data has been
212 * received.
213 */
214 synchronized void receivedLast() {
215 closedByWriter = true;
216 notifyAll();
217 }
218
219 /**
220 * Reads the next character of data from this piped stream.
221 * If no character is available because the end of the stream
222 * has been reached, the value <code>-1</code> is returned.
223 * This method blocks until input data is available, the end of
224 * the stream is detected, or an exception is thrown.
271
272 /**
273 * Reads up to <code>len</code> characters of data from this piped
274 * stream into an array of characters. Less than <code>len</code> characters
275 * will be read if the end of the data stream is reached or if
276 * <code>len</code> exceeds the pipe's buffer size. This method
277 * blocks until at least one character of input is available.
278 *
279 * @param cbuf the buffer into which the data is read.
280 * @param off the start offset of the data.
281 * @param len the maximum number of characters read.
282 * @return the total number of characters read into the buffer, or
283 * <code>-1</code> if there is no more data because the end of
284 * the stream has been reached.
285 * @exception IOException if the pipe is
286 * <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
287 * {@link #connect(java.io.PipedWriter) unconnected}, closed,
288 * or an I/O error occurs.
289 * @exception IndexOutOfBoundsException {@inheritDoc}
290 */
291 public synchronized int read(char cbuf[], int off, int len) throws IOException {
292 if (!connected) {
293 throw new IOException("Pipe not connected");
294 } else if (closedByReader) {
295 throw new IOException("Pipe closed");
296 } else if (writeSide != null && !writeSide.isAlive()
297 && !closedByWriter && (in < 0)) {
298 throw new IOException("Write end dead");
299 }
300
301 if ((off < 0) || (off > cbuf.length) || (len < 0) ||
302 ((off + len) > cbuf.length) || ((off + len) < 0)) {
303 throw new IndexOutOfBoundsException();
304 } else if (len == 0) {
305 return 0;
306 }
307
308 /* possibly wait on the first character */
309 int c = read();
310 if (c < 0) {
311 return -1;
|
36 public class PipedReader extends Reader {
37 boolean closedByWriter = false;
38 boolean closedByReader = false;
39 boolean connected = false;
40
41 /* REMIND: identification of the read and write sides needs to be
42 more sophisticated. Either using thread groups (but what about
43 pipes within a thread?) or using finalization (but it may be a
44 long time until the next GC). */
45 Thread readSide;
46 Thread writeSide;
47
48 /**
49 * The size of the pipe's circular input buffer.
50 */
51 private static final int DEFAULT_PIPE_SIZE = 1024;
52
53 /**
54 * The circular buffer into which incoming data is placed.
55 */
56 char[] buffer;
57
58 /**
59 * The index of the position in the circular buffer at which the
60 * next character of data will be stored when received from the connected
61 * piped writer. <code>in<0</code> implies the buffer is empty,
62 * <code>in==out</code> implies the buffer is full
63 */
64 int in = -1;
65
66 /**
67 * The index of the position in the circular buffer at which the next
68 * character of data will be read by this piped reader.
69 */
70 int out = 0;
71
72 /**
73 * Creates a <code>PipedReader</code> so
74 * that it is connected to the piped writer
75 * <code>src</code>. Data written to <code>src</code>
76 * will then be available as input from this stream.
184 try {
185 wait(1000);
186 } catch (InterruptedException ex) {
187 throw new java.io.InterruptedIOException();
188 }
189 }
190 if (in < 0) {
191 in = 0;
192 out = 0;
193 }
194 buffer[in++] = (char) c;
195 if (in >= buffer.length) {
196 in = 0;
197 }
198 }
199
200 /**
201 * Receives data into an array of characters. This method will
202 * block until some input is available.
203 */
204 synchronized void receive(char[] c, int off, int len) throws IOException {
205 while (--len >= 0) {
206 receive(c[off++]);
207 }
208 }
209
210 /**
211 * Notifies all waiting threads that the last character of data has been
212 * received.
213 */
214 synchronized void receivedLast() {
215 closedByWriter = true;
216 notifyAll();
217 }
218
219 /**
220 * Reads the next character of data from this piped stream.
221 * If no character is available because the end of the stream
222 * has been reached, the value <code>-1</code> is returned.
223 * This method blocks until input data is available, the end of
224 * the stream is detected, or an exception is thrown.
271
272 /**
273 * Reads up to <code>len</code> characters of data from this piped
274 * stream into an array of characters. Less than <code>len</code> characters
275 * will be read if the end of the data stream is reached or if
276 * <code>len</code> exceeds the pipe's buffer size. This method
277 * blocks until at least one character of input is available.
278 *
279 * @param cbuf the buffer into which the data is read.
280 * @param off the start offset of the data.
281 * @param len the maximum number of characters read.
282 * @return the total number of characters read into the buffer, or
283 * <code>-1</code> if there is no more data because the end of
284 * the stream has been reached.
285 * @exception IOException if the pipe is
286 * <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
287 * {@link #connect(java.io.PipedWriter) unconnected}, closed,
288 * or an I/O error occurs.
289 * @exception IndexOutOfBoundsException {@inheritDoc}
290 */
291 public synchronized int read(char[] cbuf, int off, int len) throws IOException {
292 if (!connected) {
293 throw new IOException("Pipe not connected");
294 } else if (closedByReader) {
295 throw new IOException("Pipe closed");
296 } else if (writeSide != null && !writeSide.isAlive()
297 && !closedByWriter && (in < 0)) {
298 throw new IOException("Write end dead");
299 }
300
301 if ((off < 0) || (off > cbuf.length) || (len < 0) ||
302 ((off + len) > cbuf.length) || ((off + len) < 0)) {
303 throw new IndexOutOfBoundsException();
304 } else if (len == 0) {
305 return 0;
306 }
307
308 /* possibly wait on the first character */
309 int c = read();
310 if (c < 0) {
311 return -1;
|