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 }