上卷 程序设计
中卷 标准库
- bufio 1.18
- bytes 1.18
- io 1.18
- container 1.18
- encoding 1.18
- crypto 1.18
- hash 1.18
- index 1.18
- sort 1.18
- context 1.18
- database 1.18
- connection
- query
- queryrow
- exec
- prepare
- transaction
- scan & null
- context
- tcp
- udp
- http
- server
- handler
- client
- h2、tls
- url
- rpc
- exec
- signal
- embed 1.18
- plugin 1.18
- reflect 1.18
- runtime 1.18
- KeepAlived
- ReadMemStats
- SetFinalizer
- Stack
- sync 1.18
- atomic
- mutex
- rwmutex
- waitgroup
- cond
- once
- map
- pool
- copycheck
- nocopy
- unsafe 1.18
- fmt 1.18
- log 1.18
- math 1.18
- time 1.18
- timer
下卷 运行时
源码剖析
附录
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
7.2 队列
在清理 span 时,会检查终结器,并将其添加到待执行队列。
// mgcsweep.go func (s *mspan) sweep(preserve bool) bool { size := s.elemsize specialp := &s.specials special := *specialp for special != nil { // 计算关联对象实际地址。 objIndex := uintptr(special.offset) / size p := s.base() + objIndex*size // 检查扫描标记。如可回收,则可执行终结函数。 mbits := s.markBitsForIndex(objIndex) if !mbits.isMarked() { // 未标记,表示可回收。 // 1: 得有终结器。 hasFin := false endOffset := p - s.base() + size // 同一对象,除了 finalizer,还有 profile,都在这个链表内。 // 所以,要循环检查。 for tmp := special; tmp != nil && uintptr(tmp.offset) < endOffset; tmp = tmp.next { if tmp.kind == _KindSpecialFinalizer { // 重新标记目标,使其存活,停止回收。 mbits.setMarkedNonAtomic() hasFin = true break } } // 2: 放入待运行队列。 for special != nil && uintptr(special.offset) < endOffset { p := s.base() + uintptr(special.offset) if special.kind == _KindSpecialFinalizer || !hasFin { // 从链表移除。 y := special special = special.next *specialp = special // 添加到待执行队列。 freespecial(y, unsafe.Pointer(p), size) } else { // This is profile record, but the object has finalizers (so kept alive). // Keep special record. specialp = &special.next special = *specialp } } } else { // object is still live: keep special record specialp = &special.next special = *specialp } } }
// mheap.go func freespecial(s *special, p unsafe.Pointer, size uintptr) { switch s.kind { case _KindSpecialFinalizer: // 转换指针类型,获取调用信息,添加到队列。 // 在 specialfinalizer 结构中,special 是第一个字段。 sf := (*specialfinalizer)(unsafe.Pointer(s)) queuefinalizer(p, sf.fn, sf.nret, sf.fint, sf.ot) mheap_.specialfinalizeralloc.free(unsafe.Pointer(sf)) case _KindSpecialProfile: ... } }
待执行队列 finq,由多个 finblock 构成链表。
每个 finblock 用数组存储一批 finalizer 对象。
还有个 finc 做为后备缓存。
// mfinal.go var finq *finblock // 待执行队列。 var finc *finblock // 缓存。 type finblock struct { alllink *finblock next *finblock cnt uint32 fin [(_FinBlockSize - 2*sys.PtrSize - 2*4) / unsafe.Sizeof(finalizer{})]finalizer } type finalizer struct { fn *funcval // 终结函数。 arg unsafe.Pointer // 关联对象指针。 nret uintptr fint *_type ot *ptrtype }
// mfinal.go func queuefinalizer(p unsafe.Pointer, fn *funcval, nret uintptr, fint *_type, ot *ptrtype) { // 队列未分配或已满,重新申请。 if finq == nil || finq.cnt == uint32(len(finq.fin)) { if finc == nil { finc = (*finblock)(persistentalloc(_FinBlockSize, 0, &memstats.gc_sys)) finc.alllink = allfin allfin = finc } block := finc finc = block.next block.next = finq finq = block } // 设置信息,存入队列。 f := &finq.fin[finq.cnt] atomic.Xadd(&finq.cnt, +1) // Sync with markroots f.fn = fn f.nret = nret f.fint = fint f.ot = ot f.arg = p // 设置唤醒标记。 fingwake = true }
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论