Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit 808e8fc

Browse files
committed
stop arbiter if all meters are stopped
1 parent cac0b30 commit 808e8fc

File tree

2 files changed

+43
-24
lines changed

2 files changed

+43
-24
lines changed

meter.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,7 @@ func NewMeter() Meter {
3838
return NilMeter{}
3939
}
4040
m := newStandardMeter()
41-
arbiter.Lock()
42-
defer arbiter.Unlock()
43-
arbiter.meters[m] = struct{}{}
44-
if !arbiter.started {
45-
arbiter.started = true
46-
go arbiter.tick()
47-
}
41+
m.startArbiter()
4842
return m
4943
}
5044

@@ -145,9 +139,7 @@ func newStandardMeter() *StandardMeter {
145139
// Stop stops the meter, Mark() will be a no-op if you use it after being stopped.
146140
func (m *StandardMeter) Stop() {
147141
if atomic.CompareAndSwapUint32(&m.stopped, 0, 1) {
148-
arbiter.Lock()
149-
delete(arbiter.meters, m)
150-
arbiter.Unlock()
142+
m.stopArbiter()
151143
}
152144
}
153145

@@ -156,7 +148,7 @@ func (m *StandardMeter) Count() int64 {
156148
return atomic.LoadInt64(&m.snapshot.count)
157149
}
158150

159-
// Mark records the occurance of n events.
151+
// Mark records the occurrance of n events.
160152
func (m *StandardMeter) Mark(n int64) {
161153
if atomic.LoadUint32(&m.stopped) == 1 {
162154
return
@@ -221,23 +213,54 @@ func (m *StandardMeter) tick() {
221213
m.updateSnapshot()
222214
}
223215

216+
func (m *StandardMeter) startArbiter() {
217+
arbiter.Lock()
218+
defer arbiter.Unlock()
219+
arbiter.meters[m] = struct{}{}
220+
if !arbiter.started {
221+
arbiter.started = true
222+
go arbiter.tick()
223+
}
224+
}
225+
226+
func (m *StandardMeter) stopArbiter() {
227+
arbiter.Lock()
228+
defer arbiter.Unlock()
229+
delete(arbiter.meters, m)
230+
if len(arbiter.meters) == 0 && arbiter.started {
231+
arbiter.cancel <- struct{}{}
232+
arbiter.started = false
233+
}
234+
}
235+
224236
// meterArbiter ticks meters every 5s from a single goroutine.
225237
// meters are references in a set for future stopping.
226238
type meterArbiter struct {
227239
sync.RWMutex
228-
started bool
229-
meters map[*StandardMeter]struct{}
230-
ticker *time.Ticker
240+
started bool
241+
meters map[*StandardMeter]struct{}
242+
cancel chan struct{}
243+
interval time.Duration
231244
}
232245

233-
var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})}
246+
func newArbiter(d time.Duration) *meterArbiter {
247+
return &meterArbiter{
248+
meters: make(map[*StandardMeter]struct{}),
249+
cancel: make(chan struct{}),
250+
interval: d,
251+
}
252+
}
234253

235254
// Ticks meters on the scheduled interval
236255
func (ma *meterArbiter) tick() {
256+
ticker := time.NewTicker(ma.interval)
257+
defer ticker.Stop()
237258
for {
238259
select {
239-
case <-ma.ticker.C:
260+
case <-ticker.C:
240261
ma.tickMeters()
262+
case <-ma.cancel:
263+
return
241264
}
242265
}
243266
}
@@ -249,3 +272,5 @@ func (ma *meterArbiter) tickMeters() {
249272
meter.tick()
250273
}
251274
}
275+
276+
var arbiter = newArbiter(5 * time.Second)

meter_test.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ func BenchmarkMeterParallel(b *testing.B) {
2828
// exercise race detector
2929
func TestMeterConcurrency(t *testing.T) {
3030
rand.Seed(time.Now().Unix())
31-
ma := meterArbiter{
32-
ticker: time.NewTicker(time.Millisecond),
33-
meters: make(map[*StandardMeter]struct{}),
34-
}
31+
ma := newArbiter(time.Millisecond)
3532
m := newStandardMeter()
3633
ma.meters[m] = struct{}{}
3734
go ma.tick()
@@ -61,10 +58,7 @@ func TestGetOrRegisterMeter(t *testing.T) {
6158
}
6259

6360
func TestMeterDecay(t *testing.T) {
64-
ma := meterArbiter{
65-
ticker: time.NewTicker(time.Millisecond),
66-
meters: make(map[*StandardMeter]struct{}),
67-
}
61+
ma := newArbiter(time.Millisecond)
6862
m := newStandardMeter()
6963
ma.meters[m] = struct{}{}
7064
go ma.tick()

0 commit comments

Comments
 (0)