소스 검색

Make metrics 32-bit safe

Jeff Hodges 14 년 전
부모
커밋
7598ab361f
4개의 변경된 파일24개의 추가작업 그리고 28개의 파일을 삭제
  1. 0 2
      README.md
  2. 4 7
      counter.go
  3. 16 13
      ewma.go
  4. 4 6
      gauge.go

+ 0 - 2
README.md

@@ -3,8 +3,6 @@ go-metrics
 
 Go port of Coda Hale's Metrics library: <https://github.com/codahale/metrics>.
 
-**This code is not safe on 32-bit architectures.  It will be as soon as `atomic.LoadInt64` lands in a release tag.**
-
 Usage
 -----
 

+ 4 - 7
counter.go

@@ -14,9 +14,7 @@ type Counter interface {
 }
 
 // The standard implementation of a Counter uses the sync/atomic package
-// to manage a single int64 value.  When the latest weeklies land in a
-// release, atomic.LoadInt64 will be available and this code will become
-// safe on 32-bit architectures.
+// to manage a single int64 value.
 type StandardCounter struct {
 	count int64
 }
@@ -28,13 +26,12 @@ func NewCounter() *StandardCounter {
 
 // Clear the counter: set it to zero.
 func (c *StandardCounter) Clear() {
-	c.count = 0
+	atomic.StoreInt64(&c.count, 0)
 }
 
-// Return the current count.  This is the method that's currently unsafe
-// on 32-bit architectures.
+// Return the current count.
 func (c *StandardCounter) Count() int64 {
-	return c.count
+	return atomic.LoadInt64(&c.count)
 }
 
 // Decrement the counter by the given amount.

+ 16 - 13
ewma.go

@@ -18,21 +18,20 @@ type EWMA interface {
 
 // The standard implementation of an EWMA tracks the number of uncounted
 // events and processes them on each tick.  It uses the sync/atomic package
-// to manage uncounted events.  When the latest weeklies land in a release,
-// atomic.LoadInt64 will be available and this code will become safe on
-// 32-bit architectures.
+// to manage uncounted events.
 type StandardEWMA struct {
 	alpha float64
 	uncounted int64
 	rate float64
 	initialized bool
 	tick chan bool
+	out chan float64
 }
 
 // Create a new EWMA with the given alpha.  Create the clock channel and
 // start the ticker goroutine.
 func NewEWMA(alpha float64) *StandardEWMA {
-	a := &StandardEWMA{alpha, 0, 0.0, false, make(chan bool)}
+	a := &StandardEWMA{alpha, 0, 0.0, false, make(chan bool), make(chan float64)}
 	go a.ticker()
 	return a
 }
@@ -70,15 +69,19 @@ func (a *StandardEWMA) Update(n int64) {
 // On each clock tick, update the moving average to reflect the number of
 // events seen since the last tick.
 func (a *StandardEWMA) ticker() {
-	for <-a.tick {
-		count := a.uncounted
-		atomic.AddInt64(&a.uncounted, -count)
-		instantRate := float64(count) / float64(5e9)
-		if a.initialized {
-			a.rate += a.alpha * (instantRate - a.rate)
-		} else {
-			a.initialized = true
-			a.rate = instantRate
+	for {
+		select {
+		case <-a.tick:
+			count := atomic.LoadInt64(&a.uncounted)
+			atomic.AddInt64(&a.uncounted, -count)
+			instantRate := float64(count) / float64(5e9)
+			if a.initialized {
+				a.rate += a.alpha * (instantRate - a.rate)
+			} else {
+				a.initialized = true
+				a.rate = instantRate
+			}
+		case a.out <- a.rate:
 		}
 	}
 }

+ 4 - 6
gauge.go

@@ -1,6 +1,6 @@
 package metrics
 
-import _ "sync/atomic"
+import "sync/atomic"
 
 // Gauges hold an int64 value that can be set arbitrarily.
 //
@@ -12,9 +12,7 @@ type Gauge interface {
 }
 
 // The standard implementation of a Gauge uses the sync/atomic package
-// to manage a single int64 value.  When the latest weeklies land in a
-// release, atomic.LoadInt64 will be available and this code will become
-// safe on 32-bit architectures.
+// to manage a single int64 value.
 type StandardGauge struct {
 	value int64
 }
@@ -26,10 +24,10 @@ func NewGauge() *StandardGauge {
 
 // Update the gauge's value.
 func (g *StandardGauge) Update(v int64) {
-	g.value = v
+	atomic.StoreInt64(&g.value, v)
 }
 
 // Return the gauge's current value.
 func (g *StandardGauge) Value() int64 {
-	return g.value
+	return atomic.LoadInt64(&g.value)
 }