Explorar o código

Don't hold the lock during Each callbacks.

Richard Crowley %!s(int64=12) %!d(string=hai) anos
pai
achega
b58f988162
Modificáronse 2 ficheiros con 41 adicións e 6 borrados
  1. 14 6
      registry.go
  2. 27 0
      registry_test.go

+ 14 - 6
registry.go

@@ -28,8 +28,8 @@ type Registry interface {
 // The standard implementation of a Registry is a mutex-protected map
 // of names to metrics.
 type StandardRegistry struct {
-	mutex   *sync.Mutex
 	metrics map[string]interface{}
+	mutex   *sync.Mutex
 }
 
 // Force the compiler to check that StandardRegistry implements Registry.
@@ -38,16 +38,14 @@ var _ Registry = &StandardRegistry{}
 // Create a new registry.
 func NewRegistry() *StandardRegistry {
 	return &StandardRegistry{
-		&sync.Mutex{},
-		make(map[string]interface{}),
+		metrics: make(map[string]interface{}),
+		mutex: &sync.Mutex{},
 	}
 }
 
 // Call the given function for each registered metric.
 func (r *StandardRegistry) Each(f func(string, interface{})) {
-	r.mutex.Lock()
-	defer r.mutex.Unlock()
-	for name, i := range r.metrics {
+	for name, i := range r.registered() {
 		f(name, i)
 	}
 }
@@ -87,6 +85,16 @@ func (r *StandardRegistry) Unregister(name string) {
 	delete(r.metrics, name)
 }
 
+func (r *StandardRegistry) registered() map[string]interface{} {
+	metrics := make(map[string]interface{}, len(r.metrics))
+	r.mutex.Lock()
+	defer r.mutex.Unlock()
+	for name, i := range r.metrics {
+		metrics[name] = i
+	}
+	return metrics
+}
+
 var DefaultRegistry *StandardRegistry = NewRegistry()
 
 // Call the given function for each registered metric.

+ 27 - 0
registry_test.go

@@ -0,0 +1,27 @@
+package metrics
+
+import "testing"
+
+func TestRegistry(t *testing.T) {
+	r := NewRegistry()
+	r.Register("foo", NewCounter())
+	i := 0
+	r.Each(func(name string, iface interface{}) {
+		i++
+		if "foo" != name {
+			t.Fatal(name)
+		}
+		if _, ok := iface.(Counter); !ok {
+			t.Fatal(iface)
+		}
+	})
+	if 1 != i {
+		t.Fatal(i)
+	}
+	r.Unregister("foo")
+	i = 0
+	r.Each(func(string, interface{}) { i++ })
+	if 0 != i {
+		t.Fatal(i)
+	}
+}