< prev index next >

src/java.base/share/classes/sun/nio/cs/StreamDecoder.java

Print this page
@@ -40,10 +40,11 @@
  import java.nio.charset.CharsetDecoder;
  import java.nio.charset.CoderResult;
  import java.nio.charset.CodingErrorAction;
  import java.nio.charset.IllegalCharsetNameException;
  import java.nio.charset.UnsupportedCharsetException;
+ import jdk.internal.misc.InternalLock;
  
  public class StreamDecoder extends Reader {
  
      private static final int MIN_BYTE_BUFFER_SIZE = 32;
      private static final int DEFAULT_BYTE_BUFFER_SIZE = 8192;

@@ -120,93 +121,145 @@
  
      public int read() throws IOException {
          return read0();
      }
  
-     @SuppressWarnings("fallthrough")
      private int read0() throws IOException {
-         synchronized (lock) {
- 
-             // Return the leftover char, if there is one
-             if (haveLeftoverChar) {
-                 haveLeftoverChar = false;
-                 return leftoverChar;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 return lockedRead0();
+             } finally {
+                 locker.unlock();
              }
- 
-             // Convert more bytes
-             char[] cb = new char[2];
-             int n = read(cb, 0, 2);
-             switch (n) {
-             case -1:
-                 return -1;
-             case 2:
-                 leftoverChar = cb[1];
-                 haveLeftoverChar = true;
-                 // FALL THROUGH
-             case 1:
-                 return cb[0];
-             default:
-                 assert false : n;
-                 return -1;
+         } else {
+             synchronized (lock) {
+                 return lockedRead0();
              }
          }
      }
  
+     @SuppressWarnings("fallthrough")
+     private int lockedRead0() throws IOException {
+         // Return the leftover char, if there is one
+         if (haveLeftoverChar) {
+             haveLeftoverChar = false;
+             return leftoverChar;
+         }
+ 
+         // Convert more bytes
+         char[] cb = new char[2];
+         int n = read(cb, 0, 2);
+         switch (n) {
+         case -1:
+             return -1;
+         case 2:
+             leftoverChar = cb[1];
+             haveLeftoverChar = true;
+             // FALL THROUGH
+         case 1:
+             return cb[0];
+         default:
+             assert false : n;
+             return -1;
+         }
+     }
+ 
      public int read(char[] cbuf, int offset, int length) throws IOException {
-         int off = offset;
-         int len = length;
-         synchronized (lock) {
-             ensureOpen();
-             if ((off < 0) || (off > cbuf.length) || (len < 0) ||
-                 ((off + len) > cbuf.length) || ((off + len) < 0)) {
-                 throw new IndexOutOfBoundsException();
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 return lockedRead(cbuf, offset, length);
+             } finally {
+                 locker.unlock();
              }
-             if (len == 0)
-                 return 0;
- 
-             int n = 0;
- 
-             if (haveLeftoverChar) {
-                 // Copy the leftover char into the buffer
-                 cbuf[off] = leftoverChar;
-                 off++; len--;
-                 haveLeftoverChar = false;
-                 n = 1;
-                 if ((len == 0) || !implReady())
-                     // Return now if this is all we can produce w/o blocking
-                     return n;
+         } else {
+             synchronized (lock) {
+                 return lockedRead(cbuf, offset, length);
              }
+         }
+     }
  
-             if (len == 1) {
-                 // Treat single-character array reads just like read()
-                 int c = read0();
-                 if (c == -1)
-                     return (n == 0) ? -1 : n;
-                 cbuf[off] = (char)c;
-                 return n + 1;
-             }
+     private int lockedRead(char[] cbuf, int offset, int length) throws IOException {
+         int off = offset;
+         int len = length;
+ 
+         ensureOpen();
+         if ((off < 0) || (off > cbuf.length) || (len < 0) ||
+             ((off + len) > cbuf.length) || ((off + len) < 0)) {
+             throw new IndexOutOfBoundsException();
+         }
+         if (len == 0)
+             return 0;
+ 
+         int n = 0;
+ 
+         if (haveLeftoverChar) {
+             // Copy the leftover char into the buffer
+             cbuf[off] = leftoverChar;
+             off++; len--;
+             haveLeftoverChar = false;
+             n = 1;
+             if ((len == 0) || !implReady())
+                 // Return now if this is all we can produce w/o blocking
+                 return n;
+         }
  
-             return n + implRead(cbuf, off, off + len);
+         if (len == 1) {
+             // Treat single-character array reads just like read()
+             int c = read0();
+             if (c == -1)
+                 return (n == 0) ? -1 : n;
+             cbuf[off] = (char)c;
+             return n + 1;
          }
+ 
+         return n + implRead(cbuf, off, off + len);
      }
  
      public boolean ready() throws IOException {
-         synchronized (lock) {
-             ensureOpen();
-             return haveLeftoverChar || implReady();
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
+             try {
+                 return lockedReady();
+             } finally {
+                 locker.unlock();
+             }
+         } else {
+             synchronized (lock) {
+                 return lockedReady();
+             }
          }
      }
  
+     private boolean lockedReady() throws IOException {
+         ensureOpen();
+         return haveLeftoverChar || implReady();
+     }
+ 
      public void close() throws IOException {
-         synchronized (lock) {
-             if (closed)
-                 return;
+         if (lock instanceof InternalLock locker) {
+             locker.lock();
              try {
-                 implClose();
+                 lockedClose();
              } finally {
-                 closed = true;
+                 locker.unlock();
              }
+         } else {
+             synchronized (lock) {
+                 lockedClose();
+             }
+         }
+     }
+ 
+     private void lockedClose() throws IOException {
+         if (closed)
+             return;
+         try {
+             implClose();
+         } finally {
+             closed = true;
          }
      }
  
      private boolean isOpen() {
          return !closed;

@@ -234,11 +287,11 @@
          super(lock);
          this.cs = dec.charset();
          this.decoder = dec;
          this.in = in;
          this.ch = null;
-         bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
+         this.bb = ByteBuffer.allocate(DEFAULT_BYTE_BUFFER_SIZE);
          bb.flip();                      // So that bb is initially empty
      }
  
      StreamDecoder(ReadableByteChannel ch, CharsetDecoder dec, int mbc) {
          this.in = null;
< prev index next >