diff options
author | Rob Pike <r@golang.org> | 2010-12-13 13:52:19 -0800 |
---|---|---|
committer | Rob Pike <r@golang.org> | 2010-12-13 13:52:19 -0800 |
commit | 2ef09148a0ca70bb6a164df0ee615adc137f071d (patch) | |
tree | c8be2bc1dac286a73d748b89d2d41c66dc70626a | |
parent | 1b31c37428d48ab3e5e4b86a6851293418fbf328 (diff) | |
download | go-2ef09148a0ca70bb6a164df0ee615adc137f071d.tar.gz go-2ef09148a0ca70bb6a164df0ee615adc137f071d.zip |
time: fix bug in Ticker: shutdown using channel rather than memory
R=rsc
CC=golang-dev
https://golang.org/cl/3609042
-rw-r--r-- | src/pkg/time/tick.go | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go index 9fb308396e..047468b81f 100644 --- a/src/pkg/time/tick.go +++ b/src/pkg/time/tick.go @@ -14,13 +14,16 @@ type Ticker struct { C <-chan int64 // The channel on which the ticks are delivered. c chan<- int64 // The same channel, but the end we use. ns int64 - shutdown bool + shutdown chan bool // Buffered channel used to signal shutdown. nextTick int64 next *Ticker } // Stop turns off a ticker. After Stop, no more ticks will be sent. -func (t *Ticker) Stop() { t.shutdown = true } +func (t *Ticker) Stop() { + // Make it non-blocking so multiple Stops don't block. + _ = t.shutdown <- true +} // Tick is a convenience wrapper for NewTicker providing access to the ticking // channel only. Useful for clients that have no need to shut down the ticker. @@ -116,7 +119,7 @@ func tickerLoop() { // that need it and determining the next wake time. // TODO(r): list should be sorted in time order. for t := tickers; t != nil; t = t.next { - if t.shutdown { + if _, ok := <-t.shutdown; ok { // Ticker is done; remove it from list. if prev == nil { tickers = t.next @@ -166,7 +169,13 @@ func NewTicker(ns int64) *Ticker { return nil } c := make(chan int64, 1) // See comment on send in tickerLoop - t := &Ticker{c, c, ns, false, Nanoseconds() + ns, nil} + t := &Ticker{ + C: c, + c: c, + ns: ns, + shutdown: make(chan bool, 1), + nextTick: Nanoseconds() + ns, + } onceStartTickerLoop.Do(startTickerLoop) // must be run in background so global Tickers can be created go func() { newTicker <- t }() |