buffer.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package alloc
  2. import (
  3. "time"
  4. )
  5. type Buffer struct {
  6. head []byte
  7. pool *bufferPool
  8. Value []byte
  9. }
  10. func (b *Buffer) Release() {
  11. b.pool.free(b)
  12. }
  13. func (b *Buffer) Clear() {
  14. b.Value = b.Value[:0]
  15. }
  16. func (b *Buffer) Append(data []byte) {
  17. b.Value = append(b.Value, data...)
  18. }
  19. func (b *Buffer) Slice(from, to int) {
  20. b.Value = b.Value[from:to]
  21. }
  22. func (b *Buffer) SliceFrom(from int) {
  23. b.Value = b.Value[from:]
  24. }
  25. func (b *Buffer) Len() int {
  26. return len(b.Value)
  27. }
  28. type bufferPool struct {
  29. chain chan *Buffer
  30. allocator func(*bufferPool) *Buffer
  31. elements2Keep int
  32. }
  33. func newBufferPool(allocator func(*bufferPool) *Buffer, elements2Keep, size int) *bufferPool {
  34. pool := &bufferPool{
  35. chain: make(chan *Buffer, size),
  36. allocator: allocateSmall,
  37. elements2Keep: elements2Keep,
  38. }
  39. for i := 0; i < elements2Keep; i++ {
  40. pool.chain <- allocator(pool)
  41. }
  42. go pool.cleanup(time.Tick(1 * time.Second))
  43. return pool
  44. }
  45. func (p *bufferPool) allocate() *Buffer {
  46. var b *Buffer
  47. select {
  48. case b = <-p.chain:
  49. default:
  50. b = p.allocator(p)
  51. }
  52. b.Value = b.head
  53. return b
  54. }
  55. func (p *bufferPool) free(buffer *Buffer) {
  56. select {
  57. case p.chain <- buffer:
  58. default:
  59. }
  60. }
  61. func (p *bufferPool) cleanup(tick <-chan time.Time) {
  62. for range tick {
  63. pSize := len(p.chain)
  64. if pSize > p.elements2Keep {
  65. <-p.chain
  66. continue
  67. }
  68. for delta := pSize - p.elements2Keep; delta > 0; delta-- {
  69. p.chain <- p.allocator(p)
  70. }
  71. }
  72. }
  73. func allocateSmall(pool *bufferPool) *Buffer {
  74. b := &Buffer{
  75. head: make([]byte, 8*1024),
  76. }
  77. b.Value = b.head
  78. b.pool = pool
  79. return b
  80. }
  81. var smallPool = newBufferPool(allocateSmall, 256, 2048)
  82. func NewBuffer() *Buffer {
  83. return smallPool.allocate()
  84. }