aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2010-12-13 13:52:19 -0800
committerRob Pike <r@golang.org>2010-12-13 13:52:19 -0800
commit2ef09148a0ca70bb6a164df0ee615adc137f071d (patch)
treec8be2bc1dac286a73d748b89d2d41c66dc70626a
parent1b31c37428d48ab3e5e4b86a6851293418fbf328 (diff)
downloadgo-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.go17
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 }()