pool.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package sftp
  2. // bufPool provides a pool of byte-slices to be reused in various parts of the package.
  3. // It is safe to use concurrently through a pointer.
  4. type bufPool struct {
  5. ch chan []byte
  6. blen int
  7. }
  8. func newBufPool(depth, bufLen int) *bufPool {
  9. return &bufPool{
  10. ch: make(chan []byte, depth),
  11. blen: bufLen,
  12. }
  13. }
  14. func (p *bufPool) Get() []byte {
  15. if p.blen <= 0 {
  16. panic("bufPool: new buffer creation length must be greater than zero")
  17. }
  18. for {
  19. select {
  20. case b := <-p.ch:
  21. if cap(b) < p.blen {
  22. // just in case: throw away any buffer with insufficient capacity.
  23. continue
  24. }
  25. return b[:p.blen]
  26. default:
  27. return make([]byte, p.blen)
  28. }
  29. }
  30. }
  31. func (p *bufPool) Put(b []byte) {
  32. if p == nil {
  33. // functional default: no reuse.
  34. return
  35. }
  36. if cap(b) < p.blen || cap(b) > p.blen*2 {
  37. // DO NOT reuse buffers with insufficient capacity.
  38. // This could cause panics when resizing to p.blen.
  39. // DO NOT reuse buffers with excessive capacity.
  40. // This could cause memory leaks.
  41. return
  42. }
  43. select {
  44. case p.ch <- b:
  45. default:
  46. }
  47. }
  48. type resChanPool chan chan result
  49. func newResChanPool(depth int) resChanPool {
  50. return make(chan chan result, depth)
  51. }
  52. func (p resChanPool) Get() chan result {
  53. select {
  54. case ch := <-p:
  55. return ch
  56. default:
  57. return make(chan result, 1)
  58. }
  59. }
  60. func (p resChanPool) Put(ch chan result) {
  61. select {
  62. case p <- ch:
  63. default:
  64. }
  65. }