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 }