< prev index next >

src/java.base/share/classes/java/io/BufferedInputStream.java

Print this page
@@ -23,10 +23,11 @@
   * questions.
   */
  
  package java.io;
  
+ import jdk.internal.misc.InternalLock;
  import jdk.internal.misc.Unsafe;
  import jdk.internal.util.ArraysSupport;
  
  /**
   * A {@code BufferedInputStream} adds

@@ -61,10 +62,13 @@
      private static final Unsafe U = Unsafe.getUnsafe();
  
      private static final long BUF_OFFSET
              = U.objectFieldOffset(BufferedInputStream.class, "buf");
  
+     // initialized to null when BufferedInputStream is sub-classed
+     private final InternalLock lock;
+ 
      /**
       * The internal buffer array where the data is stored. When necessary,
       * it may be replaced by another array of
       * a different size.
       */

@@ -197,16 +201,23 @@
          super(in);
          if (size <= 0) {
              throw new IllegalArgumentException("Buffer size <= 0");
          }
          buf = new byte[size];
+ 
+         // use monitors when BufferedInputStream is sub-classed
+         if (getClass() == BufferedInputStream.class) {
+             lock = new InternalLock();
+         } else {
+             lock = null;
+         }
      }
  
      /**
       * Fills the buffer with more data, taking into account
       * shuffling and other tricks for dealing with marks.
-      * Assumes that it is being called by a synchronized method.
+      * Assumes that it is being called by a locked method.
       * This method also assumes that all data has already been read in,
       * hence pos > count.
       */
      private void fill() throws IOException {
          byte[] buffer = getBufIfOpen();

@@ -256,11 +267,26 @@
       * @throws     IOException  if this input stream has been closed by
       *                          invoking its {@link #close()} method,
       *                          or an I/O error occurs.
       * @see        java.io.FilterInputStream#in
       */
-     public synchronized int read() throws IOException {
+     public int read() throws IOException {
+         if (lock != null) {
+             lock.lock();
+             try {
+                 return lockedRead();
+             } finally {
+                 lock.unlock();
+             }
+         } else {
+             synchronized (this) {
+                 return lockedRead();
+             }
+         }
+     }
+ 
+     private int lockedRead() throws IOException {
          if (pos >= count) {
              fill();
              if (pos >= count)
                  return -1;
          }

@@ -326,13 +352,26 @@
       *             the stream has been reached.
       * @throws     IOException  if this input stream has been closed by
       *                          invoking its {@link #close()} method,
       *                          or an I/O error occurs.
       */
-     public synchronized int read(byte[] b, int off, int len)
-         throws IOException
-     {
+     public int read(byte[] b, int off, int len) throws IOException {
+         if (lock != null) {
+             lock.lock();
+             try {
+                 return lockedRead(b, off, len);
+             } finally {
+                 lock.unlock();
+             }
+         } else {
+             synchronized (this) {
+                 return lockedRead(b, off, len);
+             }
+         }
+     }
+ 
+     private int lockedRead(byte[] b, int off, int len) throws IOException {
          getBufIfOpen(); // Check for closed stream
          if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
              throw new IndexOutOfBoundsException();
          } else if (len == 0) {
              return 0;

@@ -360,11 +399,26 @@
       * @throws IOException  if this input stream has been closed by
       *                      invoking its {@link #close()} method,
       *                      {@code in.skip(n)} throws an IOException,
       *                      or an I/O error occurs.
       */
-     public synchronized long skip(long n) throws IOException {
+     public long skip(long n) throws IOException {
+         if (lock != null) {
+             lock.lock();
+             try {
+                 return lockedSkip(n);
+             } finally {
+                 lock.unlock();
+             }
+         } else {
+             synchronized (this) {
+                 return lockedSkip(n);
+             }
+         }
+     }
+ 
+     private long lockedSkip(long n) throws IOException {
          getBufIfOpen(); // Check for closed stream
          if (n <= 0) {
              return 0;
          }
          long avail = count - pos;

@@ -401,11 +455,26 @@
       *             over) from this input stream without blocking.
       * @throws     IOException  if this input stream has been closed by
       *                          invoking its {@link #close()} method,
       *                          or an I/O error occurs.
       */
-     public synchronized int available() throws IOException {
+     public int available() throws IOException {
+         if (lock != null) {
+             lock.lock();
+             try {
+                 return lockAvailable();
+             } finally {
+                 lock.unlock();
+             }
+         } else {
+             synchronized (this) {
+                 return lockAvailable();
+             }
+         }
+     }
+ 
+     private int lockAvailable() throws IOException {
          int n = count - pos;
          int avail = getInIfOpen().available();
          return n > (Integer.MAX_VALUE - avail)
                      ? Integer.MAX_VALUE
                      : n + avail;

@@ -417,11 +486,26 @@
       *
       * @param   readlimit   the maximum limit of bytes that can be read before
       *                      the mark position becomes invalid.
       * @see     java.io.BufferedInputStream#reset()
       */
-     public synchronized void mark(int readlimit) {
+     public void mark(int readlimit) {
+         if (lock != null) {
+             lock.lock();
+             try {
+                 lockedMark(readlimit);
+             } finally {
+                 lock.unlock();
+             }
+         } else {
+             synchronized (this) {
+                 lockedMark(readlimit);
+             }
+         }
+     }
+ 
+     private void lockedMark(int readlimit) {
          marklimit = readlimit;
          markpos = pos;
      }
  
      /**

@@ -438,11 +522,26 @@
       *                  if the mark has been invalidated, or the stream
       *                  has been closed by invoking its {@link #close()}
       *                  method, or an I/O error occurs.
       * @see        java.io.BufferedInputStream#mark(int)
       */
-     public synchronized void reset() throws IOException {
+     public void reset() throws IOException {
+         if (lock != null) {
+             lock.lock();
+             try {
+                 lockedReset();
+             } finally {
+                 lock.unlock();
+             }
+         } else {
+             synchronized (this) {
+                 lockedReset();
+             }
+         }
+     }
+ 
+     private void lockedReset() throws IOException {
          getBufIfOpen(); // Cause exception if closed
          if (markpos < 0)
              throw new IOException("Resetting to invalid mark");
          pos = markpos;
      }
< prev index next >