github.com/songzhibin97/gkit@v1.2.13/gctuner/finalizer.go (about) 1 package gctuner 2 3 import ( 4 "runtime" 5 "sync/atomic" 6 ) 7 8 type finalizerCallback func() 9 10 type finalizer struct { 11 ref *finalizerRef 12 callback finalizerCallback 13 stopped int32 14 } 15 16 func (f *finalizer) stop() { 17 atomic.StoreInt32(&f.stopped, 1) 18 } 19 20 type finalizerRef struct { 21 parent *finalizer 22 } 23 24 func finalizerHandler(f *finalizerRef) { 25 // stop calling callback 26 27 if atomic.LoadInt32(&f.parent.stopped) == 1 { 28 return 29 } 30 f.parent.callback() 31 runtime.SetFinalizer(f, finalizerHandler) 32 } 33 34 // newFinalizer return a finalizer object and caller should save it to make sure it will not be gc. 35 // the go runtime promise the callback function should be called every gc time. 36 func newFinalizer(callback finalizerCallback) *finalizer { 37 f := &finalizer{ 38 callback: callback, 39 } 40 f.ref = &finalizerRef{parent: f} 41 runtime.SetFinalizer(f.ref, finalizerHandler) 42 f.ref = nil // trigger gc 43 return f 44 }