Class ResizingPipedInputStream

java.lang.Object
java.io.InputStream
com.amazon.ion.impl.ResizingPipedInputStream
All Implemented Interfaces:
Closeable, AutoCloseable

public class ResizingPipedInputStream extends InputStream
Manages a resizing buffer for production and consumption of data within a single thread. Buffered bytes may be consumed through the InputStream interface. This provides a few benefits over using a PipedOutputStream/PipedInputStream pair in a single thread:
  1. There is no risk of deadlock. Piped streams, which are intended for producing data in one thread and consuming it in another, will block on read when no data is available and block on write when the buffer is full. In a single-threaded context, avoiding deadlock on read requires checking that bytes are available before every read. Avoiding deadlock on write would require checking that the buffer is not full before every write, but there is no built-in, publicly-accessible way of doing this with a PipedInputStream/PipedOutputStream.
  2. The buffer can grow. Piped streams use a fixed-size buffer that causes blocking when full. If used in a single-thread, this serves as a hard limit on the amount of data that can be written without a matching read. This can require arbitrary limits on data size to be imposed by the application. The ResizingPipedInputStream imposes no such limitation, but optionally allows for a maximum buffer size to be configured to protect against unbounded growth.
  • Constructor Details

    • ResizingPipedInputStream

      public ResizingPipedInputStream(int initialBufferSize)
      Constructor.
      Parameters:
      initialBufferSize - the initial size of the buffer. When full, the buffer will grow by this many bytes. The buffer always stores bytes contiguously, so growth requires allocation of a new buffer capable of holding the new capacity and copying of the existing bytes into the new buffer. As such, a size should be chosen carefully such that growth is expected to occur rarely, if ever.
  • Method Details

    • receive

      public void receive(int b)
      Buffers a single additional byte, growing the buffer if it is already full.
      Parameters:
      b - the byte to buffer.
    • receive

      public void receive(byte[] b, int off, int len)
      Buffers `len` additional bytes, growing the buffer if it is already full or if it would become full by writing `len` bytes.
      Parameters:
      b - the bytes to buffer.
      off - the offset into `b` that points to the first byte to buffer.
      len - the number of bytes to buffer.
    • receive

      public void receive(byte[] b)
      Buffers `b.length` additional bytes.
      Parameters:
      b - the bytes to buffer.
      See Also:
    • receive

      public int receive(InputStream input, int len) throws IOException
      Buffers up to `len` additional bytes, growing the buffer if it is already full or if it would become full by writing `len` bytes. This method will block if and only if the given `InputStream`'s InputStream.read(byte[], int, int) blocks when trying to read `len` bytes. If this is not desired, the caller should ensure that the given `InputStream` has at least `len` bytes available before calling this method or provide an InputStream implementation that does not block.
      Parameters:
      input - the source of the bytes.
      len - the number of bytes to attempt to write.
      Returns:
      the number of bytes actually written, which will only be less than `len` if InputStream.read(byte[], int, int) returns less than `len`.
      Throws:
      IOException - if thrown by the given `InputStream` during read, except for EOFException. If an EOFException is thrown by the `InputStream`, it will be caught and this method will return the number of bytes that were received before the exception was thrown.
    • read

      public int read(byte[] b, int off, int len)

      NOTE: This method adheres to the documented behavior of InputStream.read(byte[], int, int) except that it never blocks. If a read is attempted before the first write, this method will return -1.

      Overrides:
      read in class InputStream
    • copyTo

      public void copyTo(OutputStream outputStream) throws IOException
      Copies all of the available bytes in the buffer without changing the number of bytes available to subsequent reads.
      Parameters:
      outputStream - stream to which the bytes will be copied.
      Throws:
      IOException - if thrown by OutputStream.write(byte[], int, int).
    • skip

      public long skip(long n)
      Skips up to `n` buffered bytes. Less than `n` bytes will be skipped if less than `n` bytes are available in the buffer.
      Overrides:
      skip in class InputStream
      Parameters:
      n - the number of bytes to skip.
      Returns:
      the number of bytes actually skipped.
    • available

      public int available()

      NOTE: This method adheres to the documented behavior of InputStream.available() except that it always returns the exact number of bytes that are available in the buffer.

      Overrides:
      available in class InputStream
      Returns:
      the exact number of bytes available in the buffer.
    • read

      public int read()

      NOTE: This method adheres to the documented behavior of InputStream.read(byte[], int, int) except that it never blocks. If a read is attempted before the first write, this method will return -1.

      Specified by:
      read in class InputStream
    • capacity

      public int capacity()
      Returns:
      the capacity of the buffer, which is always less than or equal to 'maximumBufferSize'.