| package sftp |
| |
| // bufPool provides a pool of byte-slices to be reused in various parts of the package. |
| // It is safe to use concurrently through a pointer. |
| type bufPool struct { |
| ch chan []byte |
| blen int |
| } |
| |
| func newBufPool(depth, bufLen int) *bufPool { |
| return &bufPool{ |
| ch: make(chan []byte, depth), |
| blen: bufLen, |
| } |
| } |
| |
| func (p *bufPool) Get() []byte { |
| if p.blen <= 0 { |
| panic("bufPool: new buffer creation length must be greater than zero") |
| } |
| |
| for { |
| select { |
| case b := <-p.ch: |
| if cap(b) < p.blen { |
| // just in case: throw away any buffer with insufficient capacity. |
| continue |
| } |
| |
| return b[:p.blen] |
| |
| default: |
| return make([]byte, p.blen) |
| } |
| } |
| } |
| |
| func (p *bufPool) Put(b []byte) { |
| if p == nil { |
| // functional default: no reuse. |
| return |
| } |
| |
| if cap(b) < p.blen || cap(b) > p.blen*2 { |
| // DO NOT reuse buffers with insufficient capacity. |
| // This could cause panics when resizing to p.blen. |
| |
| // DO NOT reuse buffers with excessive capacity. |
| // This could cause memory leaks. |
| return |
| } |
| |
| select { |
| case p.ch <- b: |
| default: |
| } |
| } |
| |
| type resChanPool chan chan result |
| |
| func newResChanPool(depth int) resChanPool { |
| return make(chan chan result, depth) |
| } |
| |
| func (p resChanPool) Get() chan result { |
| select { |
| case ch := <-p: |
| return ch |
| default: |
| return make(chan result, 1) |
| } |
| } |
| |
| func (p resChanPool) Put(ch chan result) { |
| select { |
| case p <- ch: |
| default: |
| } |
| } |