github.com/lingyao2333/mo-zero@v1.4.1/core/syncx/pool.go (about) 1 package syncx 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/lingyao2333/mo-zero/core/timex" 8 ) 9 10 type ( 11 // PoolOption defines the method to customize a Pool. 12 PoolOption func(*Pool) 13 14 node struct { 15 item interface{} 16 next *node 17 lastUsed time.Duration 18 } 19 20 // A Pool is used to pool resources. 21 // The difference between sync.Pool is that: 22 // 1. the limit of the resources 23 // 2. max age of the resources can be set 24 // 3. the method to destroy resources can be customized 25 Pool struct { 26 limit int 27 created int 28 maxAge time.Duration 29 lock sync.Locker 30 cond *sync.Cond 31 head *node 32 create func() interface{} 33 destroy func(interface{}) 34 } 35 ) 36 37 // NewPool returns a Pool. 38 func NewPool(n int, create func() interface{}, destroy func(interface{}), opts ...PoolOption) *Pool { 39 if n <= 0 { 40 panic("pool size can't be negative or zero") 41 } 42 43 lock := new(sync.Mutex) 44 pool := &Pool{ 45 limit: n, 46 lock: lock, 47 cond: sync.NewCond(lock), 48 create: create, 49 destroy: destroy, 50 } 51 52 for _, opt := range opts { 53 opt(pool) 54 } 55 56 return pool 57 } 58 59 // Get gets a resource. 60 func (p *Pool) Get() interface{} { 61 p.lock.Lock() 62 defer p.lock.Unlock() 63 64 for { 65 if p.head != nil { 66 head := p.head 67 p.head = head.next 68 if p.maxAge > 0 && head.lastUsed+p.maxAge < timex.Now() { 69 p.created-- 70 p.destroy(head.item) 71 continue 72 } else { 73 return head.item 74 } 75 } 76 77 if p.created < p.limit { 78 p.created++ 79 return p.create() 80 } 81 82 p.cond.Wait() 83 } 84 } 85 86 // Put puts a resource back. 87 func (p *Pool) Put(x interface{}) { 88 if x == nil { 89 return 90 } 91 92 p.lock.Lock() 93 defer p.lock.Unlock() 94 95 p.head = &node{ 96 item: x, 97 next: p.head, 98 lastUsed: timex.Now(), 99 } 100 p.cond.Signal() 101 } 102 103 // WithMaxAge returns a function to customize a Pool with given max age. 104 func WithMaxAge(duration time.Duration) PoolOption { 105 return func(pool *Pool) { 106 pool.maxAge = duration 107 } 108 }