github.com/sandwich-go/boost@v1.3.29/xpool/reference.go (about) 1 package xpool 2 3 import ( 4 "fmt" 5 "sync" 6 "sync/atomic" 7 ) 8 9 // Reference 引用 10 type Reference interface { 11 set(interface{}) 12 incr() 13 14 // Decr 引用计数减一,当引用为0时,会添入对象池中 15 Decr() 16 } 17 18 // ReferencePool 引用池 19 type ReferencePool interface { 20 // Get 获取对象 21 Get() interface{} 22 // Stats 池子状态 23 Stats() ReferencePoolStats 24 } 25 26 // ReferencePoolStats 引用池子状态 27 type ReferencePoolStats struct { 28 Released uint32 29 Allocated uint32 30 Referenced uint32 31 } 32 33 func (s ReferencePoolStats) String() string { 34 return fmt.Sprintf("Released: %d, Allocated: %d, Referenced: %d", s.Released, s.Allocated, s.Referenced) 35 } 36 37 type reference struct { 38 count *uint32 // 引用计数 39 pool *sync.Pool // 释放的目标池 40 released *uint32 // 释放次数 41 instance interface{} // 目标对象 42 reset func(interface{}) // 重置函数 43 id uint32 // 唯一标记 44 } 45 46 func (c *reference) set(i interface{}) { c.instance = i } 47 func (c *reference) incr() { atomic.AddUint32(c.count, 1) } 48 49 // Decr 减少引用计数 50 func (c *reference) Decr() { 51 if atomic.LoadUint32(c.count) == 0 { 52 return 53 } 54 if atomic.AddUint32(c.count, ^uint32(0)) == 0 { 55 atomic.AddUint32(c.released, 1) 56 if c.reset != nil { 57 c.reset(c.instance) 58 } 59 c.pool.Put(c.instance) 60 c.instance = nil 61 } 62 } 63 64 type referencePool struct { 65 *sync.Pool 66 released uint32 67 allocated uint32 68 referenced uint32 69 } 70 71 func NewReferencePool(builder func(Reference) Reference, reset func(interface{})) ReferencePool { 72 p := new(referencePool) 73 p.Pool = new(sync.Pool) 74 p.Pool.New = func() interface{} { 75 atomic.AddUint32(&p.allocated, 1) 76 return builder(&reference{ 77 count: new(uint32), 78 pool: p.Pool, 79 released: &p.released, 80 reset: reset, 81 id: p.allocated, 82 }) 83 } 84 return p 85 } 86 87 func (p *referencePool) Get() interface{} { 88 c := p.Pool.Get().(Reference) 89 c.set(c) 90 atomic.AddUint32(&p.referenced, 1) 91 c.incr() 92 return c 93 } 94 95 func (p *referencePool) Stats() ReferencePoolStats { 96 return ReferencePoolStats{ 97 Allocated: atomic.LoadUint32(&p.allocated), 98 Referenced: atomic.LoadUint32(&p.referenced), 99 Released: atomic.LoadUint32(&p.released), 100 } 101 }