map.go 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. // Copyright (c) 2017 Arista Networks, Inc.
  2. // Use of this source code is governed by the Apache License 2.0
  3. // that can be found in the COPYING file.
  4. // This code was forked from the Go project, here's the original copyright header:
  5. // Copyright 2009 The Go Authors. All rights reserved.
  6. // Use of this source code is governed by a BSD-style
  7. // license that can be found in the LICENSE file.
  8. package monitor
  9. import (
  10. "bytes"
  11. "expvar"
  12. "fmt"
  13. "sync"
  14. )
  15. // Map is a string-to-Var map variable that satisfies the Var interface.
  16. // This a streamlined, more efficient version of expvar.Map, that also
  17. // supports deletion.
  18. type Map struct {
  19. m sync.Map // map[string]expvar.Var
  20. }
  21. func (v *Map) String() string {
  22. var b bytes.Buffer
  23. b.WriteByte('{')
  24. first := true
  25. v.m.Range(func(k, value interface{}) bool {
  26. if !first {
  27. b.WriteString(", ")
  28. }
  29. fmt.Fprintf(&b, "%q: %v", k, value)
  30. first = false
  31. return true
  32. })
  33. b.WriteByte('}')
  34. return b.String()
  35. }
  36. // Get atomically returns the Var for the given key or nil.
  37. func (v *Map) Get(key string) expvar.Var {
  38. i, _ := v.m.Load(key)
  39. av, _ := i.(expvar.Var)
  40. return av
  41. }
  42. // Set atomically associates the given Var to the given key.
  43. func (v *Map) Set(key string, av expvar.Var) {
  44. // Before we store the value, check to see whether the key is new. Try a Load
  45. // before LoadOrStore: LoadOrStore causes the key interface to escape even on
  46. // the Load path.
  47. if _, ok := v.m.Load(key); !ok {
  48. if _, dup := v.m.LoadOrStore(key, av); !dup {
  49. return
  50. }
  51. }
  52. v.m.Store(key, av)
  53. }
  54. // Delete atomically deletes the given key if it exists.
  55. func (v *Map) Delete(key string) {
  56. v.m.Delete(key)
  57. }
  58. // Do calls f for each entry in the map.
  59. // The map is locked during the iteration,
  60. // but existing entries may be concurrently updated.
  61. func (v *Map) Do(f func(expvar.KeyValue)) {
  62. v.m.Range(func(k, value interface{}) bool {
  63. f(expvar.KeyValue{Key: k.(string), Value: value.(expvar.Var)})
  64. return true
  65. })
  66. }
  67. // NewMap creates a new Map and publishes it with the given name.
  68. func NewMap(name string) *Map {
  69. v := new(Map)
  70. expvar.Publish(name, v)
  71. return v
  72. }