bufferedReader is an optimized implementation of io.Reader that behaves
like
```
io.MultiReader(bytes.NewReader(buffer.Bytes()), io.TeeReader(source, buffer))
```
without allocating.
This has a measurable effect on benchmarks:
```
name old time/op new time/op delta
CMuxConn-4 1.09µs ± 4% 0.99µs ±19% -9.32% (p=0.000 n=17+19)
name old alloc/op new alloc/op delta
CMuxConn-4 240B ± 0% 260B ± 0% +8.33% (p=0.000 n=20+20)
name old allocs/op new allocs/op delta
CMuxConn-4 9.00 ± 0% 5.00 ± 0% -44.44% (p=0.000 n=20+20)
```
Note that appropriate test coverage is provided by `TestRead`.
This commit closes the connections that has been buffered
on the connection channel of the cmux listeners, when the
root listener is closed. With this change it is guaranteed
that the connections are either closed or handed of to the
child listeners (returned via Accept()).
There are a couple of changes to the tests to cover corner
cases and the new behavior.
When the root listener is closed, child listeners will not be closed
until all parked connections are served. This prevents losing
connections that have been read from.
This also allows moving the main test to package cmux_test, but that
will happen in a separate change.
cmux.go:28:1: exported method ErrNotMatched.Temporary should have comment or be unexported
cmux.go:29:1: exported method ErrNotMatched.Timeout should have comment or be unexported
cmux.go:38:2: exported var ErrListenerClosed should have comment or be unexported
cmux.go:165:6: exported type MuxConn should have comment or be unexported
As reported in #4, when the root listener is closed, calling Accept
on mux'd listeners would block forever, instead of returning an error.
This is because of a bug introduced in b90740d.
This commit fixes#4 by selecting on both donec and connc of muxed
listeners.
Added a test case to guard against this issue.
If a matcher go-routine mateches a connection after the root
listener was closed, cmux will panic since all connection channels
will be closed. This commit avoids closing connection channels but
signals the matcher go-routines that the listener is closed via
a done channel.
Tested: Added a test case for this issue.