sync
Pool
使用
type Pool struct {
New func() interface{}
}
func (p *Pool) Put(x interface{})
func (p *Pool) Get() interface{}源码分析
对象清理
数据结构

Example - fmt
Last updated
type Pool struct {
New func() interface{}
}
func (p *Pool) Put(x interface{})
func (p *Pool) Get() interface{}
Last updated
// sync/pool.go
var (
allPoolsMu Mutex
allPools []*Pool
oldPools []*Pool
)
func init() {
runtime_registerPoolCleanup(poolCleanup)
}
func poolCleanup() {
for _, p := range oldPools {
p.victim = nil
p.victimSize = 0
}
for _, p := range allPools {
p.victim = p.local
p.victimSize = p.localSize
p.local = nil
p.localSize = 0
}
oldPools, allPools = allPools, nil
}
// Implemented in runtime.
func runtime_registerPoolCleanup(cleanup func())type Pool struct {
local unsafe.Pointer // 指向 []poolLocal
localSize uintptr
}
type poolLocal struct {
poolLocalInternal
}
type poolLocalInternal struct {
private interface{}
shared poolChain
}
func (p *Pool) pinSlow() (*poolLocal, int) {
size := runtime.GOMAXPROCS(0)
local := make([]poolLocal, size)
atomic.StorePointer(&p.local, unsafe.Pointer(&local[0])) // store-release
return &local[pid], pid
}func (p *Pool) Get() interface{} {
l, pid := p.pin() // 获取 gorouting 对应的 P 的 localPool
x := l.private // 优先访问 private
l.private = nil
if x == nil {
// 若 private 为 nil,则去访问对应 P 的 localPool 的 poolChain
x, _ = l.shared.popHead()
if x == nil {
// 若这个 poolChain 中没有,则去其它 P 的 poolChain 中获取
x = p.getSlow(pid)
}
}
// 若都没有则新建
if x == nil && p.New != nil {
x = p.New()
}
return x
}func (p *Pool) Put(x interface{}) {
l, _ := p.pin() // 获取 gorouting 对应的 P 的 localPool
if l.private == nil {
// 若 private 为 nil,则置为 private
l.private = x
x = nil
}
// 否则,放入 shared
if x != nil {
l.shared.pushHead(x)
}
}// fmt/print.go
var ppFree = sync.Pool{
New: func() interface{} { return new(pp) },
}
// 使用时先重置
func newPrinter() *pp {
p := ppFree.Get().(*pp)
p.panicking = false
p.erroring = false
p.wrapErrs = false
p.fmt.init(&p.buf)
return p
}
// 归还时也情况其内容
func (p *pp) free() {
if cap(p.buf) > 64<<10 {
return
}
p.buf = p.buf[:0]
p.arg = nil
p.value = reflect.Value{}
p.wrappedErr = nil
ppFree.Put(p)
}