A source and a sink that are attached. The sink's output is the source's input. Typically each
is accessed by its own thread: a producer thread writes data to the sink and a consumer thread
reads data from the source.
This class uses a buffer to decouple source and sink. This buffer has a user-specified maximum
size. When a producer thread outruns its consumer the buffer fills up and eventually writes to
the sink will block until the consumer has caught up. Symmetrically, if a consumer outruns its
producer reads block until there is data to be read. Limits on the amount of time spent waiting
for the other party can be configured with timeouts on the source and the
sink.
When the sink is closed, source reads will continue to complete normally until the buffer has
been exhausted. At that point reads will return -1, indicating the end of the stream. But if the
source is closed first, writes to the sink will immediately fail with an IOException
.