Package uk.ac.starlink.util

# Class PipeReaderThread

java.lang.Object
java.lang.Thread
uk.ac.starlink.util.PipeReaderThread

All Implemented Interfaces:
  `Runnable`

public abstract class PipeReaderThread extends Thread
Thread which reads data from a pipe. Having got an instance of this class, you can call its getOutputStream method to acquire a stream to write into, and then implement its `doReading(java.io.InputStream)` method to process the data; this method runs in the new thread.

Here is an example of using the class to count the bytes written down a stream:

         PipeReaderThread reader = new PipeReaderThread() {
            protected void doReading( InputStream dataIn ) throws IOException {
                int i;
                while ( dataIn.read() >= 0 ) i++;
                System.out.println( i );
            }
         };
         reader.start();
         OutputStream dataOut = reader.getOutputStream();
         // write bytes down dataOut ...
         dataOut.close();
         reader.finishReading();

Other uses will look pretty similar, but just override `doReading` in different ways. Note that any exceptions thrown by `doReading` are caught and eventually thrown in the reader thread by `finishReading`. The same exception may also be thrown by the `write` method of the writer thread.

This class serves two purposes. Firstly it copes with IOExceptions encountered during the read, and makes sure they get thrown at the writing end of the pipe (`doReading` is declared to throw `IOException`). Secondly it shields the user from the implementation of the piped connection. Performance of the `PipedInputStream`/`PipedOutputStream` is dismal - this class may be able to do better.

The current implementation uses a couple of drop-in Piped*Stream replacements, but performance still isn't great - it may be possible to do better in future. You can provide your own paired pipes by overriding both `getInputStream()` and `getOutputStream()`.

Author:
  Mark Taylor (Starlink)

## Nested Class Summary

## Nested classes/interfaces inherited from class java.lang.Thread

`Thread.Builder, Thread.State, Thread.UncaughtExceptionHandler`

## Field Summary

### Fields inherited from class java.lang.Thread

`MAX_PRIORITY, MIN_PRIORITY, NORM_PRIORITY`

## Constructor Summary

Constructors
Constructor
Description
`PipeReaderThread()`
Constructs a new reader thread.

## Method Summary

Modifier and Type
Method
Description
`protected abstract void`
`doReading(InputStream dataIn)`
This method should be implemented to consume all the bytes in the given input stream.
`void`
`finishReading()`
Waits until the `doReading` method has finished reading the bytes written down the output stream, closes the input stream, and returns.
`protected InputStream`
`getInputStream()`
Returns the stream at the input end of the pipe.
`OutputStream`
`getOutputStream()`
Returns the stream at the output end of the pipe.
`void`
`run()`
Implements the thread's `run` method to invoke doReading, catching and saving IOExceptions.

### Methods inherited from class java.lang.Thread

`activeCount, checkAccess, clone, countStackFrames, currentThread, dumpStack, enumerate, getAllStackTraces, getContextClassLoader, getDefaultUncaughtExceptionHandler, getId, getName, getPriority, getStackTrace, getState, getThreadGroup, getUncaughtExceptionHandler, holdsLock, interrupt, interrupted, isAlive, isDaemon, isInterrupted, isVirtual, join, join, join, join, ofPlatform, ofVirtual, onSpinWait, resume, setContextClassLoader, setDaemon, setDefaultUncaughtExceptionHandler, setName, setPriority, setUncaughtExceptionHandler, sleep, sleep, sleep, start, startVirtualThread, stop, suspend, threadId, toString, yield`

### Methods inherited from class java.lang.Object

`equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

## Constructor Details

### PipeReaderThread

public PipeReaderThread() throws IOException
Constructs a new reader thread.

Throws:
  `IOException`

## Method Details

### getInputStream

protected InputStream getInputStream()
Returns the stream at the input end of the pipe.

Returns:
  input stream

### getOutputStream

public OutputStream getOutputStream()
Returns the stream at the output end of the pipe.

Returns:
  output stream

### run

public void run()
Implements the thread's `run` method to invoke doReading, catching and saving IOExceptions.

Specified by:
  `run` in interface `Runnable`
Overrides:
  `run` in class `Thread`

### doReading

protected abstract void doReading(InputStream dataIn) throws IOException
This method should be implemented to consume all the bytes in the given input stream. It is probably a good idea for implementations to buffer the supplied input stream for efficiency. Note that any implementation of this method which does not read `dataIn` to the end of the stream (either closing it early or just stopping reading) may cause an IOException to be thrown in the thread which is writing to the PipedOutputStream. Implementations should not close the supplied input stream.

Parameters:
  `dataIn` - stream which will supply bytes
Throws:
  `IOException` - if any I/O error occurs; this exception will be saved and thrown later by the `finishReading` method

### finishReading

public void finishReading() throws IOException
Waits until the `doReading` method has finished reading the bytes written down the output stream, closes the input stream, and returns. Any IOException which has occurred during the read will be thrown by this method.

Throws:
  `InterruptedIOException` - if failure was caused by interruption; the `bytesTransferred` field of this exception is not set to a useful value
  `IOException` - in case of some other IO failure