From aeb871a49e8f4792b64fd80b2068eb28aab62fd7 Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sun, 10 Nov 2024 16:24:19 +0000 Subject: [PATCH] Draft: StringReader is implemented as Reader.of(String).withSynchronization --- .../share/classes/java/io/Reader.java | 99 +++++++++++++++++++ .../share/classes/java/io/StringReader.java | 36 +++---- 2 files changed, 110 insertions(+), 25 deletions(-) diff --git a/src/java.base/share/classes/java/io/Reader.java b/src/java.base/share/classes/java/io/Reader.java index 9fca28a3a96cf..a4c664c3f1b52 100644 --- a/src/java.base/share/classes/java/io/Reader.java +++ b/src/java.base/share/classes/java/io/Reader.java @@ -253,6 +253,105 @@ public void close() { }; } + /** + * Returns a variant of this {@code Reader} that is safe for concurrent use + * by multiple threads. + * + * @implNote The default implementation locks a {@code ReentrantLock} before + * each method invocation, and unlocks it afterwards. Sublasses are + * encouraged to provide an optimized implementation. + * + * @return a variant of this {@code Reader} which is safe for concurrent use + * by multiple threads. + * + * @since 24 + */ + public Reader withSynchronization() { + final Lock lock = new ReentrantLock(); + + return new Reader() { + @Override + public int read() throws IOException { + lock.lock(); + try { + return Reader.this.read(); + } finally { + lock.unlock(); + } + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + lock.lock(); + try { + return Reader.this.read(cbuf, off, len); + } finally { + lock.unlock(); + } + } + + @Override + public long skip(long n) throws IOException { + lock.lock(); + try { + return Reader.this.skip(n); + } finally { + lock.unlock(); + } + } + + @Override + public boolean ready() throws IOException { + lock.lock(); + try { + return Reader.this.ready(); + } finally { + lock.unlock(); + } + } + + @Override + public boolean markSupported() { + lock.lock(); + try { + return Reader.this.markSupported(); + } finally { + lock.unlock(); + } + } + + @Override + public void mark(int readAheadLimit) throws IOException { + lock.lock(); + try { + return Reader.this.mark(); + } finally { + lock.unlock(); + } + } + + @Override + public void reset() throws IOException { + lock.lock(); + try { + return Reader.this.reset(); + } finally { + lock.unlock(); + } + } + + @Override + public void close() { + lock.lock(); + try { + return Reader.this.close(); + } finally { + lock.unlock(); + } + } + }; + } + /** * The object used to synchronize operations on this stream. For * efficiency, a character-stream object may use an object other than diff --git a/src/java.base/share/classes/java/io/StringReader.java b/src/java.base/share/classes/java/io/StringReader.java index 719e3246adf70..6b036bd8d2d1c 100644 --- a/src/java.base/share/classes/java/io/StringReader.java +++ b/src/java.base/share/classes/java/io/StringReader.java @@ -48,7 +48,7 @@ public class StringReader extends Reader { * @param s String providing the character stream. */ public StringReader(String s) { - r = Reader.of(s); + r = Reader.of(s).withSynchronization(); } /** @@ -60,9 +60,7 @@ public StringReader(String s) { * @throws IOException If an I/O error occurs */ public int read() throws IOException { - synchronized (lock) { - return r.read(); - } + return r.read(); } /** @@ -84,9 +82,7 @@ public int read() throws IOException { * @throws IOException {@inheritDoc} */ public int read(char[] cbuf, int off, int len) throws IOException { - synchronized (lock) { - return r.read(cbuf, off, len); - } + return r.read(cbuf, off, len); } /** @@ -110,9 +106,7 @@ public int read(char[] cbuf, int off, int len) throws IOException { * @throws IOException {@inheritDoc} */ public long skip(long n) throws IOException { - synchronized (lock) { - return r.skip(n); - } + return r.skip(n); } /** @@ -123,9 +117,7 @@ public long skip(long n) throws IOException { * @throws IOException If the stream is closed */ public boolean ready() throws IOException { - synchronized (lock) { - return r.ready(); - } + return r.ready(); } /** @@ -149,9 +141,7 @@ public boolean markSupported() { * @throws IOException If an I/O error occurs */ public void mark(int readAheadLimit) throws IOException { - synchronized (lock) { - r.mark(readAheadLimit); - } + r.mark(readAheadLimit); } /** @@ -161,9 +151,7 @@ public void mark(int readAheadLimit) throws IOException { * @throws IOException If an I/O error occurs */ public void reset() throws IOException { - synchronized (lock) { - r.reset(); - } + r.reset(); } /** @@ -174,12 +162,10 @@ public void reset() throws IOException { * while there is another thread blocking on the reader. */ public void close() { - synchronized (lock) { - try { - r.close(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } + try { + r.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); } } }