github.com/theQRL/go-zond@v0.1.1/metrics/counter_float64.go (about)

     1  package metrics
     2  
     3  import (
     4  	"math"
     5  	"sync/atomic"
     6  )
     7  
     8  type CounterFloat64Snapshot interface {
     9  	Count() float64
    10  }
    11  
    12  // CounterFloat64 holds a float64 value that can be incremented and decremented.
    13  type CounterFloat64 interface {
    14  	Clear()
    15  	Dec(float64)
    16  	Inc(float64)
    17  	Snapshot() CounterFloat64Snapshot
    18  }
    19  
    20  // GetOrRegisterCounterFloat64 returns an existing CounterFloat64 or constructs and registers
    21  // a new StandardCounterFloat64.
    22  func GetOrRegisterCounterFloat64(name string, r Registry) CounterFloat64 {
    23  	if nil == r {
    24  		r = DefaultRegistry
    25  	}
    26  	return r.GetOrRegister(name, NewCounterFloat64).(CounterFloat64)
    27  }
    28  
    29  // GetOrRegisterCounterFloat64Forced returns an existing CounterFloat64 or constructs and registers a
    30  // new CounterFloat64 no matter the global switch is enabled or not.
    31  // Be sure to unregister the counter from the registry once it is of no use to
    32  // allow for garbage collection.
    33  func GetOrRegisterCounterFloat64Forced(name string, r Registry) CounterFloat64 {
    34  	if nil == r {
    35  		r = DefaultRegistry
    36  	}
    37  	return r.GetOrRegister(name, NewCounterFloat64Forced).(CounterFloat64)
    38  }
    39  
    40  // NewCounterFloat64 constructs a new StandardCounterFloat64.
    41  func NewCounterFloat64() CounterFloat64 {
    42  	if !Enabled {
    43  		return NilCounterFloat64{}
    44  	}
    45  	return &StandardCounterFloat64{}
    46  }
    47  
    48  // NewCounterFloat64Forced constructs a new StandardCounterFloat64 and returns it no matter if
    49  // the global switch is enabled or not.
    50  func NewCounterFloat64Forced() CounterFloat64 {
    51  	return &StandardCounterFloat64{}
    52  }
    53  
    54  // NewRegisteredCounterFloat64 constructs and registers a new StandardCounterFloat64.
    55  func NewRegisteredCounterFloat64(name string, r Registry) CounterFloat64 {
    56  	c := NewCounterFloat64()
    57  	if nil == r {
    58  		r = DefaultRegistry
    59  	}
    60  	r.Register(name, c)
    61  	return c
    62  }
    63  
    64  // NewRegisteredCounterFloat64Forced constructs and registers a new StandardCounterFloat64
    65  // and launches a goroutine no matter the global switch is enabled or not.
    66  // Be sure to unregister the counter from the registry once it is of no use to
    67  // allow for garbage collection.
    68  func NewRegisteredCounterFloat64Forced(name string, r Registry) CounterFloat64 {
    69  	c := NewCounterFloat64Forced()
    70  	if nil == r {
    71  		r = DefaultRegistry
    72  	}
    73  	r.Register(name, c)
    74  	return c
    75  }
    76  
    77  // counterFloat64Snapshot is a read-only copy of another CounterFloat64.
    78  type counterFloat64Snapshot float64
    79  
    80  // Count returns the value at the time the snapshot was taken.
    81  func (c counterFloat64Snapshot) Count() float64 { return float64(c) }
    82  
    83  type NilCounterFloat64 struct{}
    84  
    85  func (NilCounterFloat64) Clear()                           {}
    86  func (NilCounterFloat64) Count() float64                   { return 0.0 }
    87  func (NilCounterFloat64) Dec(i float64)                    {}
    88  func (NilCounterFloat64) Inc(i float64)                    {}
    89  func (NilCounterFloat64) Snapshot() CounterFloat64Snapshot { return NilCounterFloat64{} }
    90  
    91  // StandardCounterFloat64 is the standard implementation of a CounterFloat64 and uses the
    92  // atomic to manage a single float64 value.
    93  type StandardCounterFloat64 struct {
    94  	floatBits atomic.Uint64
    95  }
    96  
    97  // Clear sets the counter to zero.
    98  func (c *StandardCounterFloat64) Clear() {
    99  	c.floatBits.Store(0)
   100  }
   101  
   102  // Dec decrements the counter by the given amount.
   103  func (c *StandardCounterFloat64) Dec(v float64) {
   104  	atomicAddFloat(&c.floatBits, -v)
   105  }
   106  
   107  // Inc increments the counter by the given amount.
   108  func (c *StandardCounterFloat64) Inc(v float64) {
   109  	atomicAddFloat(&c.floatBits, v)
   110  }
   111  
   112  // Snapshot returns a read-only copy of the counter.
   113  func (c *StandardCounterFloat64) Snapshot() CounterFloat64Snapshot {
   114  	v := math.Float64frombits(c.floatBits.Load())
   115  	return counterFloat64Snapshot(v)
   116  }
   117  
   118  func atomicAddFloat(fbits *atomic.Uint64, v float64) {
   119  	for {
   120  		loadedBits := fbits.Load()
   121  		newBits := math.Float64bits(math.Float64frombits(loadedBits) + v)
   122  		if fbits.CompareAndSwap(loadedBits, newBits) {
   123  			break
   124  		}
   125  	}
   126  }