mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
51 lines
1.5 KiB
Go
51 lines
1.5 KiB
Go
package counters
|
|
|
|
import "sync/atomic"
|
|
|
|
// StrictMonotonicCounter is a helper struct which implements a strict monotonic
|
|
// counter. StrictMonotonicCounter is implemented using atomic operations and
|
|
// doesn't allow to set a value which is lower or equal to the already stored
|
|
// ne. The counter is implemented solely with non-blocking atomic operations for
|
|
// concurrency safety.
|
|
type StrictMonotonicCounter struct {
|
|
atomicCounter uint64
|
|
}
|
|
|
|
// NewMonotonicCounter creates new counter with initial value
|
|
func NewMonotonicCounter(initialValue uint64) StrictMonotonicCounter {
|
|
return StrictMonotonicCounter{
|
|
atomicCounter: initialValue,
|
|
}
|
|
}
|
|
|
|
// Set updates value of counter if and only if it's strictly larger than value
|
|
// which is already stored. Returns true if update was successful or false if
|
|
// stored value is larger.
|
|
func (c *StrictMonotonicCounter) Set(newValue uint64) bool {
|
|
for {
|
|
oldValue := c.Value()
|
|
if newValue <= oldValue {
|
|
return false
|
|
}
|
|
if atomic.CompareAndSwapUint64(&c.atomicCounter, oldValue, newValue) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
// Value returns value which is stored in atomic variable
|
|
func (c *StrictMonotonicCounter) Value() uint64 {
|
|
return atomic.LoadUint64(&c.atomicCounter)
|
|
}
|
|
|
|
// Increment atomically increments counter and returns updated value
|
|
func (c *StrictMonotonicCounter) Increment() uint64 {
|
|
for {
|
|
oldValue := c.Value()
|
|
newValue := oldValue + 1
|
|
if atomic.CompareAndSwapUint64(&c.atomicCounter, oldValue, newValue) {
|
|
return newValue
|
|
}
|
|
}
|
|
}
|