github.com/codingfuture/orig-energi3@v0.8.4/metrics/counter.go (about)

     1  // Copyright 2018 The Energi Core Authors
     2  // Copyright 2015 The go-ethereum Authors
     3  // This file is part of the Energi Core library.
     4  //
     5  // The Energi Core library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The Energi Core library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the Energi Core library. If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package metrics
    19  
    20  import (
    21  	"sync/atomic"
    22  )
    23  
    24  // Counters hold an int64 value that can be incremented and decremented.
    25  type Counter interface {
    26  	Clear()
    27  	Count() int64
    28  	Dec(int64)
    29  	Inc(int64)
    30  	Snapshot() Counter
    31  }
    32  
    33  // GetOrRegisterCounter returns an existing Counter or constructs and registers
    34  // a new StandardCounter.
    35  func GetOrRegisterCounter(name string, r Registry) Counter {
    36  	if nil == r {
    37  		r = DefaultRegistry
    38  	}
    39  	return r.GetOrRegister(name, NewCounter).(Counter)
    40  }
    41  
    42  // GetOrRegisterCounterForced returns an existing Counter or constructs and registers a
    43  // new Counter no matter the global switch is enabled or not.
    44  // Be sure to unregister the counter from the registry once it is of no use to
    45  // allow for garbage collection.
    46  func GetOrRegisterCounterForced(name string, r Registry) Counter {
    47  	if nil == r {
    48  		r = DefaultRegistry
    49  	}
    50  	return r.GetOrRegister(name, NewCounterForced).(Counter)
    51  }
    52  
    53  // NewCounter constructs a new StandardCounter.
    54  func NewCounter() Counter {
    55  	if !Enabled {
    56  		return NilCounter{}
    57  	}
    58  	return &StandardCounter{0}
    59  }
    60  
    61  // NewCounterForced constructs a new StandardCounter and returns it no matter if
    62  // the global switch is enabled or not.
    63  func NewCounterForced() Counter {
    64  	return &StandardCounter{0}
    65  }
    66  
    67  // NewRegisteredCounter constructs and registers a new StandardCounter.
    68  func NewRegisteredCounter(name string, r Registry) Counter {
    69  	c := NewCounter()
    70  	if nil == r {
    71  		r = DefaultRegistry
    72  	}
    73  	r.Register(name, c)
    74  	return c
    75  }
    76  
    77  // NewRegisteredCounterForced constructs and registers a new StandardCounter
    78  // and launches a goroutine no matter the global switch is enabled or not.
    79  // Be sure to unregister the counter from the registry once it is of no use to
    80  // allow for garbage collection.
    81  func NewRegisteredCounterForced(name string, r Registry) Counter {
    82  	c := NewCounterForced()
    83  	if nil == r {
    84  		r = DefaultRegistry
    85  	}
    86  	r.Register(name, c)
    87  	return c
    88  }
    89  
    90  // CounterSnapshot is a read-only copy of another Counter.
    91  type CounterSnapshot int64
    92  
    93  // Clear panics.
    94  func (CounterSnapshot) Clear() {
    95  	panic("Clear called on a CounterSnapshot")
    96  }
    97  
    98  // Count returns the count at the time the snapshot was taken.
    99  func (c CounterSnapshot) Count() int64 { return int64(c) }
   100  
   101  // Dec panics.
   102  func (CounterSnapshot) Dec(int64) {
   103  	panic("Dec called on a CounterSnapshot")
   104  }
   105  
   106  // Inc panics.
   107  func (CounterSnapshot) Inc(int64) {
   108  	panic("Inc called on a CounterSnapshot")
   109  }
   110  
   111  // Snapshot returns the snapshot.
   112  func (c CounterSnapshot) Snapshot() Counter { return c }
   113  
   114  // NilCounter is a no-op Counter.
   115  type NilCounter struct{}
   116  
   117  // Clear is a no-op.
   118  func (NilCounter) Clear() {}
   119  
   120  // Count is a no-op.
   121  func (NilCounter) Count() int64 { return 0 }
   122  
   123  // Dec is a no-op.
   124  func (NilCounter) Dec(i int64) {}
   125  
   126  // Inc is a no-op.
   127  func (NilCounter) Inc(i int64) {}
   128  
   129  // Snapshot is a no-op.
   130  func (NilCounter) Snapshot() Counter { return NilCounter{} }
   131  
   132  // StandardCounter is the standard implementation of a Counter and uses the
   133  // sync/atomic package to manage a single int64 value.
   134  type StandardCounter struct {
   135  	count int64
   136  }
   137  
   138  // Clear sets the counter to zero.
   139  func (c *StandardCounter) Clear() {
   140  	atomic.StoreInt64(&c.count, 0)
   141  }
   142  
   143  // Count returns the current count.
   144  func (c *StandardCounter) Count() int64 {
   145  	return atomic.LoadInt64(&c.count)
   146  }
   147  
   148  // Dec decrements the counter by the given amount.
   149  func (c *StandardCounter) Dec(i int64) {
   150  	atomic.AddInt64(&c.count, -i)
   151  }
   152  
   153  // Inc increments the counter by the given amount.
   154  func (c *StandardCounter) Inc(i int64) {
   155  	atomic.AddInt64(&c.count, i)
   156  }
   157  
   158  // Snapshot returns a read-only copy of the counter.
   159  func (c *StandardCounter) Snapshot() Counter {
   160  	return CounterSnapshot(c.Count())
   161  }