github.com/calmw/ethereum@v0.1.1/metrics/counter_float64.go (about)

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