123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- package syncx
- import (
- "sync"
- "time"
- "github.com/tal-tech/go-zero/core/timex"
- )
- type (
- // PoolOption defines the method to customize a Pool.
- PoolOption func(*Pool)
- node struct {
- item interface{}
- next *node
- lastUsed time.Duration
- }
- // A Pool is used to pool resources.
- // The difference between sync.Pool is that:
- // 1. the limit of the resouces
- // 2. max age of the resources can be set
- // 3. the method to destroy resources can be customized
- Pool struct {
- limit int
- created int
- maxAge time.Duration
- lock sync.Locker
- cond *sync.Cond
- head *node
- create func() interface{}
- destroy func(interface{})
- }
- )
- // NewPool returns a Pool.
- func NewPool(n int, create func() interface{}, destroy func(interface{}), opts ...PoolOption) *Pool {
- if n <= 0 {
- panic("pool size can't be negative or zero")
- }
- lock := new(sync.Mutex)
- pool := &Pool{
- limit: n,
- lock: lock,
- cond: sync.NewCond(lock),
- create: create,
- destroy: destroy,
- }
- for _, opt := range opts {
- opt(pool)
- }
- return pool
- }
- // Get gets a resouce.
- func (p *Pool) Get() interface{} {
- p.lock.Lock()
- defer p.lock.Unlock()
- for {
- if p.head != nil {
- head := p.head
- p.head = head.next
- if p.maxAge > 0 && head.lastUsed+p.maxAge < timex.Now() {
- p.created--
- p.destroy(head.item)
- continue
- } else {
- return head.item
- }
- }
- if p.created < p.limit {
- p.created++
- return p.create()
- }
- p.cond.Wait()
- }
- }
- // Put puts a resource back.
- func (p *Pool) Put(x interface{}) {
- if x == nil {
- return
- }
- p.lock.Lock()
- defer p.lock.Unlock()
- p.head = &node{
- item: x,
- next: p.head,
- lastUsed: timex.Now(),
- }
- p.cond.Signal()
- }
- // WithMaxAge returns a function to customize a Pool with given max age.
- func WithMaxAge(duration time.Duration) PoolOption {
- return func(pool *Pool) {
- pool.maxAge = duration
- }
- }
|