Fixing PipedWriters/PipedOutputStreams silent failures during close().
See bug 2224903 and jtreg test java.io.BufferedWriter.Cleanup.
diff --git a/libcore/luni/src/main/java/java/io/PipedInputStream.java b/libcore/luni/src/main/java/java/io/PipedInputStream.java
index a6b0336..6d1c007 100644
--- a/libcore/luni/src/main/java/java/io/PipedInputStream.java
+++ b/libcore/luni/src/main/java/java/io/PipedInputStream.java
@@ -15,6 +15,13 @@
* limitations under the License.
*/
+// BEGIN android-note
+// We've made several changes including:
+// - delayed buffer creation until pipe connection
+// - throw an IOException when a pipe is closed during a write
+// - improved consistency with PipedReader
+// END android-note
+
package java.io;
import org.apache.harmony.luni.util.Msg;
@@ -28,9 +35,11 @@
*/
public class PipedInputStream extends InputStream {
- private Thread lastReader, lastWriter;
+ private Thread lastReader;
- private boolean isClosed = false;
+ private Thread lastWriter;
+
+ private boolean isClosed;
/**
* The circular buffer through which data is passed. Data is read from the
@@ -60,7 +69,7 @@
/**
* The index in {@code buffer} where the next byte will be read.
*/
- protected int out = 0;
+ protected int out;
/**
* The size of the default pipe in bytes.
@@ -70,16 +79,14 @@
/**
* Indicates if this pipe is connected.
*/
- boolean isConnected = false;
+ boolean isConnected;
/**
* Constructs a new unconnected {@code PipedInputStream}. The resulting
* stream must be connected to a {@link PipedOutputStream} before data may
* be read from it.
*/
- public PipedInputStream() {
- /* empty */
- }
+ public PipedInputStream() {}
/**
* Constructs a new {@code PipedInputStream} connected to the
@@ -120,14 +127,9 @@
* if an error occurs while closing this stream.
*/
@Override
- public void close() throws IOException {
- synchronized (this) {
- /* No exception thrown if already closed */
- if (buffer != null) {
- /* Release buffer to indicate closed. */
- buffer = null;
- }
- }
+ public synchronized void close() throws IOException {
+ buffer = null;
+ notifyAll();
}
/**
@@ -145,6 +147,20 @@
}
/**
+ * Establishes the connection to the PipedOutputStream.
+ *
+ * @throws IOException
+ * If this Reader is already connected.
+ */
+ synchronized void establishConnection() throws IOException {
+ if (isConnected) {
+ throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
+ }
+ buffer = new byte[PipedInputStream.PIPE_SIZE];
+ isConnected = true;
+ }
+
+ /**
* Reads a single byte from this stream and returns it as an integer in the
* range from 0 to 255. Returns -1 if the end of this stream has been
* reached. If there is no data in the pipe, this method blocks until data
@@ -408,20 +424,21 @@
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
- if (buffer != null) {
- if (in == -1) {
- in = 0;
- }
- buffer[in++] = (byte) oneByte;
- if (in == buffer.length) {
- in = 0;
- }
-
- // BEGIN android-added
- // let blocked readers read the newly available data
- notifyAll();
- // END android-added
+ if (buffer == null) {
+ throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
}
+ if (in == -1) {
+ in = 0;
+ }
+ buffer[in++] = (byte) oneByte;
+ if (in == buffer.length) {
+ in = 0;
+ }
+
+ // BEGIN android-added
+ // let blocked readers read the newly available data
+ notifyAll();
+ // END android-added
}
synchronized void done() {
diff --git a/libcore/luni/src/main/java/java/io/PipedOutputStream.java b/libcore/luni/src/main/java/java/io/PipedOutputStream.java
index 15ee930..4b640d4 100644
--- a/libcore/luni/src/main/java/java/io/PipedOutputStream.java
+++ b/libcore/luni/src/main/java/java/io/PipedOutputStream.java
@@ -15,6 +15,12 @@
* limitations under the License.
*/
+// BEGIN android-note
+// We've made several changes including:
+// - avoid shallow concurrency problems
+// - improved consistency with PipedWriter
+// END android-note
+
package java.io;
import org.apache.harmony.luni.util.Msg;
@@ -67,8 +73,9 @@
@Override
public void close() throws IOException {
// Is the pipe connected?
- if (dest != null) {
- dest.done();
+ PipedInputStream stream = dest;
+ if (stream != null) {
+ stream.done();
dest = null;
}
}
@@ -83,18 +90,17 @@
* if either stream is already connected.
*/
public void connect(PipedInputStream stream) throws IOException {
- if (null == stream) {
+ if (stream == null) {
throw new NullPointerException();
}
- if (this.dest != null) {
- throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$
- }
synchronized (stream) {
+ if (this.dest != null) {
+ throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$
+ }
if (stream.isConnected) {
throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
}
- stream.buffer = new byte[PipedInputStream.PIPE_SIZE];
- stream.isConnected = true;
+ stream.establishConnection();
this.dest = stream;
}
}
@@ -108,10 +114,13 @@
*/
@Override
public void flush() throws IOException {
- if (dest != null) {
- synchronized (dest) {
- dest.notifyAll();
- }
+ PipedInputStream stream = dest;
+ if (stream == null) {
+ return;
+ }
+
+ synchronized (stream) {
+ stream.notifyAll();
}
}
@@ -145,13 +154,6 @@
*/
@Override
public void write(byte[] buffer, int offset, int count) throws IOException {
- // BEGIN android-note
- // changed array notation to be consistent with the rest of harmony
- // END android-note
- if (dest == null) {
- // K007b=Pipe Not Connected
- throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
- }
super.write(buffer, offset, count);
}
@@ -177,9 +179,11 @@
*/
@Override
public void write(int oneByte) throws IOException {
- if (dest == null) {
+ PipedInputStream stream = dest;
+ if (stream == null) {
+ // K007b=Pipe Not Connected
throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
}
- dest.receive(oneByte);
+ stream.receive(oneByte);
}
}
diff --git a/libcore/luni/src/main/java/java/io/PipedReader.java b/libcore/luni/src/main/java/java/io/PipedReader.java
index 251ac90..d137a0d 100644
--- a/libcore/luni/src/main/java/java/io/PipedReader.java
+++ b/libcore/luni/src/main/java/java/io/PipedReader.java
@@ -17,6 +17,13 @@
package java.io;
+// BEGIN android-note
+// We've made several changes including:
+// - throw an IOException when a pipe is closed during a write
+// - fix shallow concurrency problems, always lock on 'this'
+// - improved consistency with PipedInputStream
+// END android-note
+
import org.apache.harmony.luni.util.Msg;
/**
@@ -35,13 +42,27 @@
private boolean isClosed;
/**
- * The circular buffer through which data is passed.
+ * The circular buffer through which data is passed. Data is read from the
+ * range {@code [out, in)} and written to the range {@code [in, out)}.
+ * Data in the buffer is either sequential: <pre>
+ * { - - - X X X X X X X - - - - - }
+ * ^ ^
+ * | |
+ * out in</pre>
+ * ...or wrapped around the buffer's end: <pre>
+ * { X X X X - - - - - - - - X X X }
+ * ^ ^
+ * | |
+ * in out</pre>
+ * When the buffer is empty, {@code in == -1}. Reading when the buffer is
+ * empty will block until data is available. When the buffer is full,
+ * {@code in == out}. Writing when the buffer is full will block until free
+ * space is available.
*/
- private char data[];
+ private char[] buffer;
/**
- * The index in {@code buffer} where the next character will be
- * written.
+ * The index in {@code buffer} where the next character will be written.
*/
private int in = -1;
@@ -58,18 +79,14 @@
/**
* Indicates if this pipe is connected
*/
- private boolean isConnected;
+ boolean isConnected;
/**
* Constructs a new unconnected {@code PipedReader}. The resulting reader
* must be connected to a {@code PipedWriter} before data may be read from
* it.
- *
- * @see PipedWriter
*/
- public PipedReader() {
- data = new char[PIPE_SIZE];
- }
+ public PipedReader() {}
/**
* Constructs a new {@code PipedReader} connected to the {@link PipedWriter}
@@ -82,7 +99,6 @@
* if {@code out} is already connected.
*/
public PipedReader(PipedWriter out) throws IOException {
- this();
connect(out);
}
@@ -94,14 +110,9 @@
* if an error occurs while closing this reader.
*/
@Override
- public void close() throws IOException {
- synchronized (lock) {
- /* No exception thrown if already closed */
- if (data != null) {
- /* Release buffer to indicate closed. */
- data = null;
- }
- }
+ public synchronized void close() throws IOException {
+ buffer = null;
+ notifyAll();
}
/**
@@ -115,9 +126,7 @@
* src} is already connected.
*/
public void connect(PipedWriter src) throws IOException {
- synchronized (lock) {
- src.connect(this);
- }
+ src.connect(this);
}
/**
@@ -126,16 +135,12 @@
* @throws IOException
* If this Reader is already connected.
*/
- void establishConnection() throws IOException {
- synchronized (lock) {
- if (data == null) {
- throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
- }
- if (isConnected) {
- throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
- }
- isConnected = true;
+ synchronized void establishConnection() throws IOException {
+ if (isConnected) {
+ throw new IOException(Msg.getString("K007a")); //$NON-NLS-1$
}
+ buffer = new char[PIPE_SIZE];
+ isConnected = true;
}
/**
@@ -192,95 +197,93 @@
* alive.
*/
@Override
- public int read(char[] buffer, int offset, int count) throws IOException {
- synchronized (lock) {
- if (!isConnected) {
- throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
- }
- if (data == null) {
- throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
- }
- // avoid int overflow
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // made implicit null check explicit,
- // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
- // to safe one operation
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
- }
- if ((offset | count) < 0 || count > buffer.length - offset) {
- throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
- }
- // END android-changed
- if (count == 0) {
- return 0;
- }
- /**
- * Set the last thread to be reading on this PipedReader. If
- * lastReader dies while someone is waiting to write an IOException
- * of "Pipe broken" will be thrown in receive()
- */
- lastReader = Thread.currentThread();
- try {
- boolean first = true;
- while (in == -1) {
- // Are we at end of stream?
- if (isClosed) {
- return -1;
- }
- if (!first && lastWriter != null && !lastWriter.isAlive()) {
- throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
- }
- first = false;
- // Notify callers of receive()
- lock.notifyAll();
- lock.wait(1000);
+ public synchronized int read(char[] buffer, int offset, int count) throws IOException {
+ if (!isConnected) {
+ throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
+ }
+ if (this.buffer == null) {
+ throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+ }
+ // avoid int overflow
+ // BEGIN android-changed
+ // Exception priorities (in case of multiple errors) differ from
+ // RI, but are spec-compliant.
+ // made implicit null check explicit,
+ // used (offset | count) < 0 instead of (offset < 0) || (count < 0)
+ // to safe one operation
+ if (buffer == null) {
+ throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ }
+ if ((offset | count) < 0 || count > buffer.length - offset) {
+ throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ }
+ // END android-changed
+ if (count == 0) {
+ return 0;
+ }
+ /**
+ * Set the last thread to be reading on this PipedReader. If
+ * lastReader dies while someone is waiting to write an IOException
+ * of "Pipe broken" will be thrown in receive()
+ */
+ lastReader = Thread.currentThread();
+ try {
+ boolean first = true;
+ while (in == -1) {
+ // Are we at end of stream?
+ if (isClosed) {
+ return -1;
}
- } catch (InterruptedException e) {
- throw new InterruptedIOException();
- }
-
- int copyLength = 0;
- /* Copy chars from out to end of buffer first */
- if (out >= in) {
- copyLength = count > data.length - out ? data.length - out
- : count;
- System.arraycopy(data, out, buffer, offset, copyLength);
- out += copyLength;
- if (out == data.length) {
- out = 0;
+ if (!first && lastWriter != null && !lastWriter.isAlive()) {
+ throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
}
- if (out == in) {
- // empty buffer
- in = -1;
- out = 0;
- }
+ first = false;
+ // Notify callers of receive()
+ notifyAll();
+ wait(1000);
}
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
- /*
- * Did the read fully succeed in the previous copy or is the buffer
- * empty?
- */
- if (copyLength == count || in == -1) {
- return copyLength;
- }
-
- int charsCopied = copyLength;
- /* Copy bytes from 0 to the number of available bytes */
- copyLength = in - out > count - copyLength ? count - copyLength
- : in - out;
- System.arraycopy(data, out, buffer, offset + charsCopied,
- copyLength);
+ int copyLength = 0;
+ /* Copy chars from out to end of buffer first */
+ if (out >= in) {
+ copyLength = count > this.buffer.length - out ? this.buffer.length - out
+ : count;
+ System.arraycopy(this.buffer, out, buffer, offset, copyLength);
out += copyLength;
+ if (out == this.buffer.length) {
+ out = 0;
+ }
if (out == in) {
// empty buffer
in = -1;
out = 0;
}
- return charsCopied + copyLength;
}
+
+ /*
+ * Did the read fully succeed in the previous copy or is the buffer
+ * empty?
+ */
+ if (copyLength == count || in == -1) {
+ return copyLength;
+ }
+
+ int charsCopied = copyLength;
+ /* Copy bytes from 0 to the number of available bytes */
+ copyLength = in - out > count - copyLength ? count - copyLength
+ : in - out;
+ System.arraycopy(this.buffer, out, buffer, offset + charsCopied,
+ copyLength);
+ out += copyLength;
+ if (out == in) {
+ // empty buffer
+ in = -1;
+ out = 0;
+ }
+ return charsCopied + copyLength;
}
/**
@@ -298,16 +301,14 @@
* @see #read(char[], int, int)
*/
@Override
- public boolean ready() throws IOException {
- synchronized (lock) {
- if (!isConnected) {
- throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
- }
- if (data == null) {
- throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
- }
- return in != -1;
+ public synchronized boolean ready() throws IOException {
+ if (!isConnected) {
+ throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
}
+ if (buffer == null) {
+ throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+ }
+ return in != -1;
}
/**
@@ -324,43 +325,41 @@
* If the stream is already closed or another IOException
* occurs.
*/
- void receive(char oneChar) throws IOException {
- synchronized (lock) {
- if (data == null) {
- throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
- }
- if (lastReader != null && !lastReader.isAlive()) {
- throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
- }
- /*
- * Set the last thread to be writing on this PipedWriter. If
- * lastWriter dies while someone is waiting to read an IOException
- * of "Pipe broken" will be thrown in read()
- */
- lastWriter = Thread.currentThread();
- try {
- while (data != null && out == in) {
- lock.notifyAll();
- // BEGIN android-changed
- lock.wait(1000);
- // END android-changed
- if (lastReader != null && !lastReader.isAlive()) {
- throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
- }
+ synchronized void receive(char oneChar) throws IOException {
+ if (buffer == null) {
+ throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+ }
+ if (lastReader != null && !lastReader.isAlive()) {
+ throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+ }
+ /*
+ * Set the last thread to be writing on this PipedWriter. If
+ * lastWriter dies while someone is waiting to read an IOException
+ * of "Pipe broken" will be thrown in read()
+ */
+ lastWriter = Thread.currentThread();
+ try {
+ while (buffer != null && out == in) {
+ notifyAll();
+ // BEGIN android-changed
+ wait(1000);
+ // END android-changed
+ if (lastReader != null && !lastReader.isAlive()) {
+ throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
}
- } catch (InterruptedException e) {
- throw new InterruptedIOException();
}
- if (data != null) {
- if (in == -1) {
- in = 0;
- }
- data[in++] = oneChar;
- if (in == data.length) {
- in = 0;
- }
- return;
- }
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
+ if (buffer == null) {
+ throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+ }
+ if (in == -1) {
+ in = 0;
+ }
+ buffer[in++] = oneChar;
+ if (in == buffer.length) {
+ in = 0;
}
}
@@ -382,80 +381,73 @@
* If the stream is already closed or another IOException
* occurs.
*/
- void receive(char[] chars, int offset, int count) throws IOException {
- synchronized (lock) {
- if (data == null) {
+ synchronized void receive(char[] chars, int offset, int count) throws IOException {
+ if (chars == null) {
+ throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+ }
+ if ((offset | count) < 0 || count > chars.length - offset) {
+ throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
+ }
+ if (buffer == null) {
+ throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
+ }
+ if (lastReader != null && !lastReader.isAlive()) {
+ throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+ }
+ /**
+ * Set the last thread to be writing on this PipedWriter. If
+ * lastWriter dies while someone is waiting to read an IOException
+ * of "Pipe broken" will be thrown in read()
+ */
+ lastWriter = Thread.currentThread();
+ while (count > 0) {
+ try {
+ while (buffer != null && out == in) {
+ notifyAll();
+ // BEGIN android-changed
+ wait(1000);
+ // END android-changed
+ if (lastReader != null && !lastReader.isAlive()) {
+ throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+ }
+ }
+ } catch (InterruptedException e) {
+ throw new InterruptedIOException();
+ }
+ if (buffer == null) {
throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
}
- if (lastReader != null && !lastReader.isAlive()) {
- throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
+ if (in == -1) {
+ in = 0;
}
- /**
- * Set the last thread to be writing on this PipedWriter. If
- * lastWriter dies while someone is waiting to read an IOException
- * of "Pipe broken" will be thrown in read()
- */
- lastWriter = Thread.currentThread();
- while (count > 0) {
- try {
- while (data != null && out == in) {
- lock.notifyAll();
- // BEGIN android-changed
- lock.wait(1000);
- // END android-changed
- if (lastReader != null && !lastReader.isAlive()) {
- throw new IOException(Msg.getString("K0076")); //$NON-NLS-1$
- }
- }
- } catch (InterruptedException e) {
- throw new InterruptedIOException();
+ if (in >= out) {
+ int length = buffer.length - in;
+ if (count < length) {
+ length = count;
}
- if (data == null) {
- break;
- }
- if (in == -1) {
+ System.arraycopy(chars, offset, buffer, in, length);
+ offset += length;
+ count -= length;
+ in += length;
+ if (in == buffer.length) {
in = 0;
}
- if (in >= out) {
- int length = data.length - in;
- if (count < length) {
- length = count;
- }
- System.arraycopy(chars, offset, data, in, length);
- offset += length;
- count -= length;
- in += length;
- if (in == data.length) {
- in = 0;
- }
- }
- if (count > 0 && in != out) {
- int length = out - in;
- if (count < length) {
- length = count;
- }
- System.arraycopy(chars, offset, data, in, length);
- offset += length;
- count -= length;
- in += length;
- }
}
- if (count == 0) {
- return;
+ if (count > 0 && in != out) {
+ int length = out - in;
+ if (count < length) {
+ length = count;
+ }
+ System.arraycopy(chars, offset, buffer, in, length);
+ offset += length;
+ count -= length;
+ in += length;
}
}
}
- void done() {
- synchronized (lock) {
- isClosed = true;
- lock.notifyAll();
- }
- }
-
- void flush() {
- synchronized (lock) {
- lock.notifyAll();
- }
+ synchronized void done() {
+ isClosed = true;
+ notifyAll();
}
}
diff --git a/libcore/luni/src/main/java/java/io/PipedWriter.java b/libcore/luni/src/main/java/java/io/PipedWriter.java
index 5fc968d..b0bfa98 100644
--- a/libcore/luni/src/main/java/java/io/PipedWriter.java
+++ b/libcore/luni/src/main/java/java/io/PipedWriter.java
@@ -15,6 +15,14 @@
* limitations under the License.
*/
+// BEGIN android-note
+// We've made several changes including:
+// - move checks into the synchronized method in PipedReader
+// - reply on PipedReader's isClosed field (rather than having 2 flags)
+// - avoid shallow concurrency problems
+// - improved consistency with PipedOutputStream
+// END android-note
+
package java.io;
import org.apache.harmony.luni.util.Msg;
@@ -32,8 +40,6 @@
*/
private PipedReader dest;
- private boolean closed;
-
/**
* Constructs a new unconnected {@code PipedWriter}. The resulting writer
* must be connected to a {@code PipedReader} before data may be written to
@@ -70,13 +76,10 @@
*/
@Override
public void close() throws IOException {
- synchronized (lock) {
- /* Is the pipe connected? */
- if (dest != null) {
- dest.done();
- dest = null;
- }
- closed = true;
+ PipedReader reader = dest;
+ if (reader != null) {
+ reader.done();
+ dest = null;
}
}
@@ -84,22 +87,26 @@
* Connects this {@code PipedWriter} to a {@link PipedReader}. Any data
* written to this writer becomes readable in the reader.
*
- * @param stream
+ * @param reader
* the reader to connect to.
* @throws IOException
* if this writer is closed or already connected, or if {@code
- * stream} is already connected.
+ * reader} is already connected.
*/
- public void connect(PipedReader stream) throws IOException {
- synchronized (lock) {
+ public void connect(PipedReader reader) throws IOException {
+ if (reader == null) {
+ throw new NullPointerException();
+ }
+ synchronized (reader) {
if (this.dest != null) {
throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$
}
- if (closed) {
+ if (reader.isConnected) {
throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
}
- stream.establishConnection();
- this.dest = stream;
+ reader.establishConnection();
+ this.lock = reader;
+ this.dest = reader;
}
}
@@ -112,8 +119,13 @@
*/
@Override
public void flush() throws IOException {
- if (dest != null) {
- dest.flush();
+ PipedReader reader = dest;
+ if (reader == null) {
+ return;
+ }
+
+ synchronized (reader) {
+ reader.notifyAll();
}
}
@@ -150,32 +162,12 @@
*/
@Override
public void write(char[] buffer, int offset, int count) throws IOException {
- // BEGIN android-note
- // changed array notation to be consistent with the rest of harmony
- // END android-note
- synchronized (lock) {
- if (closed) {
- throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
- }
- if (dest == null) {
- throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
- }
- if (buffer == null) {
- throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
- }
-
- // avoid int overflow
- // BEGIN android-changed
- // Exception priorities (in case of multiple errors) differ from
- // RI, but are spec-compliant.
- // removed redundant check, used (offset | count) < 0
- // instead of (offset < 0) || (count < 0) to safe one operation
- if ((offset | count) < 0 || count > buffer.length - offset) {
- throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$
- }
- // END android-changed
- dest.receive(buffer, offset, count);
+ PipedReader reader = dest;
+ if (reader == null) {
+ // K007b=Pipe Not Connected
+ throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
}
+ reader.receive(buffer, offset, count);
}
/**
@@ -200,14 +192,11 @@
*/
@Override
public void write(int c) throws IOException {
- synchronized (lock) {
- if (closed) {
- throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$
- }
- if (dest == null) {
- throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
- }
- dest.receive((char) c);
+ PipedReader reader = dest;
+ if (reader == null) {
+ // K007b=Pipe Not Connected
+ throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$
}
+ reader.receive((char) c);
}
}