@@ -38,13 +38,7 @@ func NewMeter() Meter {
38
38
return NilMeter {}
39
39
}
40
40
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 ()
48
42
return m
49
43
}
50
44
@@ -145,9 +139,7 @@ func newStandardMeter() *StandardMeter {
145
139
// Stop stops the meter, Mark() will be a no-op if you use it after being stopped.
146
140
func (m * StandardMeter ) Stop () {
147
141
if atomic .CompareAndSwapUint32 (& m .stopped , 0 , 1 ) {
148
- arbiter .Lock ()
149
- delete (arbiter .meters , m )
150
- arbiter .Unlock ()
142
+ m .stopArbiter ()
151
143
}
152
144
}
153
145
@@ -156,7 +148,7 @@ func (m *StandardMeter) Count() int64 {
156
148
return atomic .LoadInt64 (& m .snapshot .count )
157
149
}
158
150
159
- // Mark records the occurance of n events.
151
+ // Mark records the occurrance of n events.
160
152
func (m * StandardMeter ) Mark (n int64 ) {
161
153
if atomic .LoadUint32 (& m .stopped ) == 1 {
162
154
return
@@ -221,23 +213,54 @@ func (m *StandardMeter) tick() {
221
213
m .updateSnapshot ()
222
214
}
223
215
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
+
224
236
// meterArbiter ticks meters every 5s from a single goroutine.
225
237
// meters are references in a set for future stopping.
226
238
type meterArbiter struct {
227
239
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
231
244
}
232
245
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
+ }
234
253
235
254
// Ticks meters on the scheduled interval
236
255
func (ma * meterArbiter ) tick () {
256
+ ticker := time .NewTicker (ma .interval )
257
+ defer ticker .Stop ()
237
258
for {
238
259
select {
239
- case <- ma . ticker .C :
260
+ case <- ticker .C :
240
261
ma .tickMeters ()
262
+ case <- ma .cancel :
263
+ return
241
264
}
242
265
}
243
266
}
@@ -249,3 +272,5 @@ func (ma *meterArbiter) tickMeters() {
249
272
meter .tick ()
250
273
}
251
274
}
275
+
276
+ var arbiter = newArbiter (5 * time .Second )
0 commit comments