@@ -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.
146140func (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.
160152func (m * StandardMeter ) Mark (n int64 ) {
161153 if atomic .LoadUint32 (& m .stopped ) == 1 {
162154 return
@@ -221,23 +213,50 @@ 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.
226238type meterArbiter struct {
227239 sync.RWMutex
228240 started bool
229241 meters map [* StandardMeter ]struct {}
230- ticker * time. Ticker
242+ cancel chan struct {}
231243}
232244
233- var arbiter = meterArbiter {ticker : time .NewTicker (5e9 ), meters : make (map [* StandardMeter ]struct {})}
245+ var arbiter = meterArbiter {
246+ meters : make (map [* StandardMeter ]struct {}),
247+ cancel : make (chan struct {}),
248+ }
234249
235250// Ticks meters on the scheduled interval
236251func (ma * meterArbiter ) tick () {
252+ ticker := time .NewTicker (5 * time .Second )
253+ defer ticker .Stop ()
237254 for {
238255 select {
239- case <- ma . ticker .C :
256+ case <- ticker .C :
240257 ma .tickMeters ()
258+ case <- ma .cancel :
259+ return
241260 }
242261 }
243262}
0 commit comments