counter.go 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package counter
  2. import (
  3. "sync"
  4. )
  5. // Counter is a counter interface.
  6. type Counter interface {
  7. Add(int64)
  8. Reset()
  9. Value() int64
  10. }
  11. // Group is a counter group.
  12. type Group struct {
  13. mu sync.RWMutex
  14. vecs map[string]Counter
  15. // New optionally specifies a function to generate a counter.
  16. // It may not be changed concurrently with calls to other functions.
  17. New func() Counter
  18. }
  19. // Add add a counter by a specified key, if counter not exists then make a new one and return new value.
  20. func (g *Group) Add(key string, value int64) {
  21. g.mu.RLock()
  22. vec, ok := g.vecs[key]
  23. g.mu.RUnlock()
  24. if !ok {
  25. vec = g.New()
  26. g.mu.Lock()
  27. if g.vecs == nil {
  28. g.vecs = make(map[string]Counter)
  29. }
  30. if _, ok = g.vecs[key]; !ok {
  31. g.vecs[key] = vec
  32. }
  33. g.mu.Unlock()
  34. }
  35. vec.Add(value)
  36. }
  37. // Value get a counter value by key.
  38. func (g *Group) Value(key string) int64 {
  39. g.mu.RLock()
  40. vec, ok := g.vecs[key]
  41. g.mu.RUnlock()
  42. if ok {
  43. return vec.Value()
  44. }
  45. return 0
  46. }
  47. // Reset reset a counter by key.
  48. func (g *Group) Reset(key string) {
  49. g.mu.RLock()
  50. vec, ok := g.vecs[key]
  51. g.mu.RUnlock()
  52. if ok {
  53. vec.Reset()
  54. }
  55. }