generic.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package pool
  2. import (
  3. "sync"
  4. "github.com/gobwas/pool/internal/pmath"
  5. )
  6. var DefaultPool = New(128, 65536)
  7. // Get pulls object whose generic size is at least of given size. It also
  8. // returns a real size of x for further pass to Put(). It returns -1 as real
  9. // size for nil x. Size >-1 does not mean that x is non-nil, so checks must be
  10. // done.
  11. //
  12. // Note that size could be ceiled to the next power of two.
  13. //
  14. // Get is a wrapper around DefaultPool.Get().
  15. func Get(size int) (interface{}, int) { return DefaultPool.Get(size) }
  16. // Put takes x and its size for future reuse.
  17. // Put is a wrapper around DefaultPool.Put().
  18. func Put(x interface{}, size int) { DefaultPool.Put(x, size) }
  19. // Pool contains logic of reusing objects distinguishable by size in generic
  20. // way.
  21. type Pool struct {
  22. pool map[int]*sync.Pool
  23. size func(int) int
  24. }
  25. // New creates new Pool that reuses objects which size is in logarithmic range
  26. // [min, max].
  27. //
  28. // Note that it is a shortcut for Custom() constructor with Options provided by
  29. // WithLogSizeMapping() and WithLogSizeRange(min, max) calls.
  30. func New(min, max int) *Pool {
  31. return Custom(
  32. WithLogSizeMapping(),
  33. WithLogSizeRange(min, max),
  34. )
  35. }
  36. // Custom creates new Pool with given options.
  37. func Custom(opts ...Option) *Pool {
  38. p := &Pool{
  39. pool: make(map[int]*sync.Pool),
  40. size: pmath.Identity,
  41. }
  42. c := (*poolConfig)(p)
  43. for _, opt := range opts {
  44. opt(c)
  45. }
  46. return p
  47. }
  48. // Get pulls object whose generic size is at least of given size.
  49. // It also returns a real size of x for further pass to Put() even if x is nil.
  50. // Note that size could be ceiled to the next power of two.
  51. func (p *Pool) Get(size int) (interface{}, int) {
  52. n := p.size(size)
  53. if pool := p.pool[n]; pool != nil {
  54. return pool.Get(), n
  55. }
  56. return nil, size
  57. }
  58. // Put takes x and its size for future reuse.
  59. func (p *Pool) Put(x interface{}, size int) {
  60. if pool := p.pool[size]; pool != nil {
  61. pool.Put(x)
  62. }
  63. }
  64. type poolConfig Pool
  65. // AddSize adds size n to the map.
  66. func (p *poolConfig) AddSize(n int) {
  67. p.pool[n] = new(sync.Pool)
  68. }
  69. // SetSizeMapping sets up incoming size mapping function.
  70. func (p *poolConfig) SetSizeMapping(size func(int) int) {
  71. p.size = size
  72. }