@@ -21,22 +21,39 @@ const defaultBufSize = 4096
2121// In other words, we can't write and read simultaneously on the same connection.
2222// The buffer is similar to bufio.Reader / Writer but zero-copy-ish
2323// Also highly optimized for this particular use case.
24+ // This buffer is backed by two byte slices in a double-buffering scheme
2425type buffer struct {
2526 buf []byte // buf is a byte buffer who's length and capacity are equal.
2627 nc net.Conn
2728 idx int
2829 length int
2930 timeout time.Duration
31+ dbuf [2 ][]byte // dbuf is an array with the two byte slices that back this buffer
32+ dbufn int // dbufn is the current buffer counter for double-buffering
3033}
3134
3235// newBuffer allocates and returns a new buffer.
3336func newBuffer (nc net.Conn ) buffer {
37+ fg := make ([]byte , defaultBufSize )
38+ bg := make ([]byte , defaultBufSize )
3439 return buffer {
35- buf : make ([]byte , defaultBufSize ),
36- nc : nc ,
40+ buf : fg ,
41+ nc : nc ,
42+ dbuf : [2 ][]byte {fg , bg },
3743 }
3844}
3945
46+ // swap replaces the active buffer with the background buffer
47+ func (b * buffer ) swap () {
48+ b .dbufn += 1
49+ dest := b .dbuf [b .dbufn & 1 ]
50+ if b .length > 0 {
51+ copy (dest [0 :b .length ], b .buf [b .idx :])
52+ }
53+ b .buf = dest
54+ b .idx = 0
55+ }
56+
4057// fill reads into the buffer until at least _need_ bytes are in it
4158func (b * buffer ) fill (need int ) error {
4259 n := b .length
@@ -47,8 +64,6 @@ func (b *buffer) fill(need int) error {
4764 }
4865
4966 // grow buffer if necessary
50- // TODO: let the buffer shrink again at some point
51- // Maybe keep the org buf slice and swap back?
5267 if need > len (b .buf ) {
5368 // Round up to the next multiple of the default size
5469 newBuf := make ([]byte , ((need / defaultBufSize )+ 1 )* defaultBufSize )
0 commit comments