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  }