github.com/bytedance/gopkg@v0.0.0-20240514070511-01b2cbcf35e1/util/gctuner/finalizer.go (about)

     1  // Copyright 2022 ByteDance Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gctuner
    16  
    17  import (
    18  	"runtime"
    19  	"sync/atomic"
    20  )
    21  
    22  type finalizerCallback func()
    23  
    24  type finalizer struct {
    25  	ref      *finalizerRef
    26  	callback finalizerCallback
    27  	stopped  int32
    28  }
    29  
    30  type finalizerRef struct {
    31  	parent *finalizer
    32  }
    33  
    34  func finalizerHandler(f *finalizerRef) {
    35  	// stop calling callback
    36  	if atomic.LoadInt32(&f.parent.stopped) > 0 {
    37  		return
    38  	}
    39  	f.parent.callback()
    40  	runtime.SetFinalizer(f, finalizerHandler)
    41  }
    42  
    43  // newFinalizer return a finalizer object and caller should save it to make sure it will not be gc.
    44  // the go runtime promise the callback function should be called every gc time.
    45  func newFinalizer(callback finalizerCallback) *finalizer {
    46  	f := &finalizer{
    47  		callback: callback,
    48  	}
    49  	f.ref = &finalizerRef{parent: f}
    50  	runtime.SetFinalizer(f.ref, finalizerHandler)
    51  	f.ref = nil // trigger gc
    52  	return f
    53  }
    54  
    55  func (f *finalizer) stop() {
    56  	atomic.StoreInt32(&f.stopped, 1)
    57  }