org.dellroad.stuff.io
Class AsyncOutputStream

java.lang.Object
  extended by java.io.OutputStream
      extended by java.io.FilterOutputStream
          extended by org.dellroad.stuff.io.AsyncOutputStream
All Implemented Interfaces:
Closeable, Flushable

public class AsyncOutputStream
extends FilterOutputStream

An OutputStream that performs writes using a background thread, so that write, flush, and close operations never block.

If the underlying output stream throws an IOException during any operation, this instance will re-throw the exception for all subsequent operations.

Instances use an internal buffer whose size is configured at construction time; if the buffer overflows, a BufferOverflowException is thrown.

Instances of this class are thread safe, and moreover writes are atomic: if multiple threads are writing at the same time the bytes written in any single method invocation are written contiguously to the underlying output.


Field Summary
protected  Logger log
           
 
Fields inherited from class java.io.FilterOutputStream
out
 
Constructor Summary
AsyncOutputStream(OutputStream out, int bufsize, String name)
          Constructor.
 
Method Summary
 int availableBufferSpace()
          Get the number of free bytes remaining in the output buffer.
 void close()
          Close this instance.
 void flush()
          Flush output.
 int getBufferSize()
          Get the capacity of this instance's output buffer.
 IOException getException()
          Get the exception thrown by the underlying output stream, if any.
 boolean isWorkOutstanding()
          Determine if there is outstanding work still to be performed (writes, flushes, and/or close operations) by the background thread.
 boolean waitForIdle(long timeout)
          Wait for all outstanding work to complete.
 boolean waitForSpace(int numBytes, long timeout)
          Wait for buffer space availability.
 void write(byte[] data, int off, int len)
          Write data.
 void write(int b)
          Write data.
 
Methods inherited from class java.io.FilterOutputStream
write
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

log

protected final Logger log
Constructor Detail

AsyncOutputStream

public AsyncOutputStream(OutputStream out,
                         int bufsize,
                         String name)
Constructor.

Parameters:
out - underlying output stream
bufsize - maximum number of bytes we can buffer
name - name for this instance; used to create the name of the background thread
Method Detail

write

public void write(int b)
           throws IOException
Write data.

This method will never block. To effect a normal blocking write, use waitForSpace(int, long) first.

Overrides:
write in class FilterOutputStream
Parameters:
b - byte to write (lower 8 bits)
Throws:
IOException - if an exception has been thrown by the underlying stream
IOException - if this instance has been closed
BufferOverflowException - if the buffer does not have room for the new byte

write

public void write(byte[] data,
                  int off,
                  int len)
           throws IOException
Write data.

This method will never block. To effect a normal blocking write, invoke waitForSpace(int, long) first.

Overrides:
write in class FilterOutputStream
Parameters:
data - bytes to write
off - starting offset in buffer
len - number of bytes to write
Throws:
IOException - if an exception has been thrown by the underlying stream
IOException - if this instance has been closed
BufferOverflowException - if the buffer does not have room for the new data
IllegalArgumentException - if len is negative

flush

public void flush()
           throws IOException
Flush output. This method will cause the underlying stream to be flushed once all of the data written to this instance at the time this method is invoked has been written to it.

If additional data is written and then a second flush is requested before the first flush has actually occurred, the first flush will be canceled and only the second flush will be applied. Normally this is not a problem because the act of writing more data and then flushing forces earlier data to be flushed as well.

This method will never block. To block until the underlying flush operation completes, invoke waitForIdle(long).

Specified by:
flush in interface Flushable
Overrides:
flush in class FilterOutputStream
Throws:
IOException - if this instance has been closed
IOException - if an exception has been detected on the underlying stream
IOException - if the current thread is interrupted; the nested exception will an InterruptedException

close

public void close()
           throws IOException
Close this instance. This will (eventually) close the underlying output stream.

If this instance has already been closed, nothing happens.

This method will never block. To block until the underlying close operation completes, invoke waitForIdle(long).

Specified by:
close in interface Closeable
Overrides:
close in class FilterOutputStream
Throws:
IOException - if an exception has been detected on the underlying stream

getException

public IOException getException()
Get the exception thrown by the underlying output stream, if any.

Returns:
thrown exception, or null if none has been thrown by the underlying stream

getBufferSize

public int getBufferSize()
Get the capacity of this instance's output buffer.

Returns:
output buffer capacity configured at construction time

availableBufferSpace

public int availableBufferSpace()
                         throws IOException
Get the number of free bytes remaining in the output buffer.

Returns:
current number of available bytes in the output buffer
Throws:
IOException - if this instance is or has been closed
IOException - if an exception has been detected on the underlying stream
See Also:
waitForSpace(int, long)

isWorkOutstanding

public boolean isWorkOutstanding()
                          throws IOException
Determine if there is outstanding work still to be performed (writes, flushes, and/or close operations) by the background thread.

Throws:
IOException - if this instance is or has been closed
IOException - if an exception has been detected on the underlying stream
See Also:
waitForIdle(long)

waitForSpace

public boolean waitForSpace(int numBytes,
                            long timeout)
                     throws IOException,
                            InterruptedException
Wait for buffer space availability.

Parameters:
numBytes - amount of buffer space required
timeout - maximum time to wait in milliseconds, or zero for infinite
Returns:
true if space was found, false if time expired
Throws:
IOException - if this instance is or has been closed
IOException - if an exception has been detected on the underlying stream
IllegalArgumentException - if numBytes is greater than the configured buffer size
IllegalArgumentException - if timeout is negative
InterruptedException - if the current thread is interrupted
See Also:
availableBufferSpace()

waitForIdle

public boolean waitForIdle(long timeout)
                    throws IOException,
                           InterruptedException
Wait for all outstanding work to complete.

Parameters:
timeout - maximum time to wait in milliseconds, or zero for infinite
Returns:
true for success, false if time expired
Throws:
IOException - if this instance is or has been closed
IOException - if an exception has been detected on the underlying stream
IllegalArgumentException - if timeout is negative
InterruptedException - if the current thread is interrupted
See Also:
isWorkOutstanding()