repeat_timer: drain channel in Stop; done -> wg

This commit is contained in:
Ethan Buchman 2017-03-05 03:24:25 -05:00
parent 6141dc6eed
commit dcb015dff6
1 changed files with 15 additions and 6 deletions

View File

@ -1,7 +1,9 @@
package common package common
import "time" import (
import "sync" "sync"
"time"
)
/* /*
RepeatTimer repeatedly sends a struct{}{} to .Ch after each "dur" period. RepeatTimer repeatedly sends a struct{}{} to .Ch after each "dur" period.
@ -15,7 +17,7 @@ type RepeatTimer struct {
name string name string
ticker *time.Ticker ticker *time.Ticker
quit chan struct{} quit chan struct{}
done chan struct{} wg *sync.WaitGroup
dur time.Duration dur time.Duration
} }
@ -24,10 +26,11 @@ func NewRepeatTimer(name string, dur time.Duration) *RepeatTimer {
Ch: make(chan time.Time), Ch: make(chan time.Time),
ticker: time.NewTicker(dur), ticker: time.NewTicker(dur),
quit: make(chan struct{}), quit: make(chan struct{}),
done: make(chan struct{}), wg: new(sync.WaitGroup),
name: name, name: name,
dur: dur, dur: dur,
} }
t.wg.Add(1)
go t.fireRoutine(t.ticker) go t.fireRoutine(t.ticker)
return t return t
} }
@ -39,7 +42,7 @@ func (t *RepeatTimer) fireRoutine(ticker *time.Ticker) {
t.Ch <- t_ t.Ch <- t_
case <-t.quit: case <-t.quit:
// needed so we know when we can reset t.quit // needed so we know when we can reset t.quit
t.done <- struct{}{} t.wg.Done()
return return
} }
} }
@ -54,6 +57,7 @@ func (t *RepeatTimer) Reset() {
t.ticker = time.NewTicker(t.dur) t.ticker = time.NewTicker(t.dur)
t.quit = make(chan struct{}) t.quit = make(chan struct{})
t.wg.Add(1)
go t.fireRoutine(t.ticker) go t.fireRoutine(t.ticker)
} }
@ -69,8 +73,13 @@ func (t *RepeatTimer) Stop() bool {
exists := t.ticker != nil exists := t.ticker != nil
if exists { if exists {
t.ticker.Stop() // does not close the channel t.ticker.Stop() // does not close the channel
select {
case <-t.Ch:
// read off channel if there's anything there
default:
}
close(t.quit) close(t.quit)
<-t.done t.wg.Wait() // must wait for quit to close else we race Reset
t.ticker = nil t.ticker = nil
} }
return exists return exists