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

Commit 3bf96d8

Browse files
author
James DeFelice
committed
meter: once all meters are stopped, reset arbiter
1 parent 3113b84 commit 3bf96d8

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

meter.go

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ func NewMeter() Meter {
4343
arbiter.meters[m] = struct{}{}
4444
if !arbiter.started {
4545
arbiter.started = true
46-
go arbiter.tick()
46+
arbiter.cancel = make(chan struct{})
47+
go arbiter.tick(arbiter.ticker, arbiter.cancel)
4748
}
4849
return m
4950
}
@@ -146,8 +147,20 @@ func newStandardMeter() *StandardMeter {
146147
func (m *StandardMeter) Stop() {
147148
if atomic.CompareAndSwapUint32(&m.stopped, 0, 1) {
148149
arbiter.Lock()
150+
defer arbiter.Unlock()
151+
149152
delete(arbiter.meters, m)
150-
arbiter.Unlock()
153+
154+
if len(arbiter.meters) > 0 {
155+
return
156+
}
157+
158+
// reset the arbiter to a newly intialized state, allows
159+
// background goroutine (arbiter.tick) to terminate cleanly.
160+
arbiter.ticker.Stop()
161+
close(arbiter.cancel)
162+
arbiter.ticker = time.NewTicker(5e9)
163+
arbiter.started = false
151164
}
152165
}
153166

@@ -228,16 +241,19 @@ type meterArbiter struct {
228241
started bool
229242
meters map[*StandardMeter]struct{}
230243
ticker *time.Ticker
244+
cancel chan struct{}
231245
}
232246

233247
var arbiter = meterArbiter{ticker: time.NewTicker(5e9), meters: make(map[*StandardMeter]struct{})}
234248

235249
// Ticks meters on the scheduled interval
236-
func (ma *meterArbiter) tick() {
250+
func (ma *meterArbiter) tick(ticker *time.Ticker, cancel <-chan struct{}) {
237251
for {
238252
select {
239-
case <-ma.ticker.C:
253+
case <-ticker.C:
240254
ma.tickMeters()
255+
case <-cancel:
256+
return
241257
}
242258
}
243259
}

meter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func TestMeterConcurrency(t *testing.T) {
3434
}
3535
m := newStandardMeter()
3636
ma.meters[m] = struct{}{}
37-
go ma.tick()
37+
go ma.tick(ma.ticker, nil)
3838
wg := &sync.WaitGroup{}
3939
reps := 100
4040
for i := 0; i < reps; i++ {
@@ -67,7 +67,7 @@ func TestMeterDecay(t *testing.T) {
6767
}
6868
m := newStandardMeter()
6969
ma.meters[m] = struct{}{}
70-
go ma.tick()
70+
go ma.tick(ma.ticker, nil)
7171
m.Mark(1)
7272
rateMean := m.RateMean()
7373
time.Sleep(100 * time.Millisecond)

0 commit comments

Comments
 (0)