pbufio.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Package pbufio contains tools for pooling bufio.Reader and bufio.Writers.
  2. package pbufio
  3. import (
  4. "bufio"
  5. "io"
  6. "github.com/gobwas/pool"
  7. )
  8. var (
  9. DefaultWriterPool = NewWriterPool(256, 65536)
  10. DefaultReaderPool = NewReaderPool(256, 65536)
  11. )
  12. // GetWriter returns bufio.Writer whose buffer has at least size bytes.
  13. // Note that size could be ceiled to the next power of two.
  14. // GetWriter is a wrapper around DefaultWriterPool.Get().
  15. func GetWriter(w io.Writer, size int) *bufio.Writer { return DefaultWriterPool.Get(w, size) }
  16. // PutWriter takes bufio.Writer for future reuse.
  17. // It does not reuse bufio.Writer which underlying buffer size is not power of
  18. // PutWriter is a wrapper around DefaultWriterPool.Put().
  19. func PutWriter(bw *bufio.Writer) { DefaultWriterPool.Put(bw) }
  20. // GetReader returns bufio.Reader whose buffer has at least size bytes. It returns
  21. // its capacity for further pass to Put().
  22. // Note that size could be ceiled to the next power of two.
  23. // GetReader is a wrapper around DefaultReaderPool.Get().
  24. func GetReader(w io.Reader, size int) *bufio.Reader { return DefaultReaderPool.Get(w, size) }
  25. // PutReader takes bufio.Reader and its size for future reuse.
  26. // It does not reuse bufio.Reader if size is not power of two or is out of pool
  27. // min/max range.
  28. // PutReader is a wrapper around DefaultReaderPool.Put().
  29. func PutReader(bw *bufio.Reader) { DefaultReaderPool.Put(bw) }
  30. // WriterPool contains logic of *bufio.Writer reuse with various size.
  31. type WriterPool struct {
  32. pool *pool.Pool
  33. }
  34. // NewWriterPool creates new WriterPool that reuses writers which size is in
  35. // logarithmic range [min, max].
  36. func NewWriterPool(min, max int) *WriterPool {
  37. return &WriterPool{pool.New(min, max)}
  38. }
  39. // CustomWriterPool creates new WriterPool with given options.
  40. func CustomWriterPool(opts ...pool.Option) *WriterPool {
  41. return &WriterPool{pool.Custom(opts...)}
  42. }
  43. // Get returns bufio.Writer whose buffer has at least size bytes.
  44. func (wp *WriterPool) Get(w io.Writer, size int) *bufio.Writer {
  45. v, n := wp.pool.Get(size)
  46. if v != nil {
  47. bw := v.(*bufio.Writer)
  48. bw.Reset(w)
  49. return bw
  50. }
  51. return bufio.NewWriterSize(w, n)
  52. }
  53. // Put takes ownership of bufio.Writer for further reuse.
  54. func (wp *WriterPool) Put(bw *bufio.Writer) {
  55. // Should reset even if we do Reset() inside Get().
  56. // This is done to prevent locking underlying io.Writer from GC.
  57. bw.Reset(nil)
  58. wp.pool.Put(bw, writerSize(bw))
  59. }
  60. // ReaderPool contains logic of *bufio.Reader reuse with various size.
  61. type ReaderPool struct {
  62. pool *pool.Pool
  63. }
  64. // NewReaderPool creates new ReaderPool that reuses writers which size is in
  65. // logarithmic range [min, max].
  66. func NewReaderPool(min, max int) *ReaderPool {
  67. return &ReaderPool{pool.New(min, max)}
  68. }
  69. // CustomReaderPool creates new ReaderPool with given options.
  70. func CustomReaderPool(opts ...pool.Option) *ReaderPool {
  71. return &ReaderPool{pool.Custom(opts...)}
  72. }
  73. // Get returns bufio.Reader whose buffer has at least size bytes.
  74. func (rp *ReaderPool) Get(r io.Reader, size int) *bufio.Reader {
  75. v, n := rp.pool.Get(size)
  76. if v != nil {
  77. br := v.(*bufio.Reader)
  78. br.Reset(r)
  79. return br
  80. }
  81. return bufio.NewReaderSize(r, n)
  82. }
  83. // Put takes ownership of bufio.Reader for further reuse.
  84. func (rp *ReaderPool) Put(br *bufio.Reader) {
  85. // Should reset even if we do Reset() inside Get().
  86. // This is done to prevent locking underlying io.Reader from GC.
  87. br.Reset(nil)
  88. rp.pool.Put(br, readerSize(br))
  89. }