From 2ef09148a0ca70bb6a164df0ee615adc137f071d Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Mon, 13 Dec 2010 13:52:19 -0800 Subject: [PATCH] time: fix bug in Ticker: shutdown using channel rather than memory R=rsc CC=golang-dev https://golang.org/cl/3609042 --- src/pkg/time/tick.go | 17 +++++++++++++---- 1 file 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 }() -- 2.50.0