summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2010-01-19 17:46:21 -0800
committerRuss Cox <rsc@golang.org>2010-01-19 17:46:21 -0800
commit290f5c4692eb53d8036e03d3499816d59550dd9c (patch)
tree381fbfff376d33fabbae5dd08278c3f54fe494d9
parentf782fb288b2a99d4b4889612727672c2f0b44185 (diff)
downloadgolang-290f5c4692eb53d8036e03d3499816d59550dd9c.tar.gz
time: make tick.Stop a little more robust
R=r CC=golang-dev, jackpal http://codereview.appspot.com/186228
-rw-r--r--src/pkg/time/tick.go36
1 files changed, 30 insertions, 6 deletions
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go
index a37e8ea4c..98576dfe3 100644
--- a/src/pkg/time/tick.go
+++ b/src/pkg/time/tick.go
@@ -24,12 +24,26 @@ package time
// at intervals.
type Ticker struct {
C <-chan int64 // The channel on which the ticks are delivered.
+ done chan bool
ns int64
shutdown bool
}
-// Stop turns off a ticker. After Stop, no more ticks will be delivered.
-func (t *Ticker) Stop() { t.shutdown = true }
+// Stop turns off a ticker. After Stop, no more ticks will be sent.
+func (t *Ticker) Stop() {
+ t.shutdown = true
+ go t.drain()
+}
+
+func (t *Ticker) drain() {
+ for {
+ select {
+ case <-t.C:
+ case <-t.done:
+ return
+ }
+ }
+}
func (t *Ticker) ticker(c chan<- int64) {
now := Nanoseconds()
@@ -47,13 +61,23 @@ func (t *Ticker) ticker(c chan<- int64) {
when += t.ns
}
- Sleep(when - now)
- now = Nanoseconds()
+ for !t.shutdown && when > now {
+ // limit individual sleeps so that stopped
+ // long-term tickers don't pile up.
+ const maxSleep = 1e9
+ if when-now > maxSleep {
+ Sleep(maxSleep)
+ } else {
+ Sleep(when - now)
+ }
+ now = Nanoseconds()
+ }
if t.shutdown {
- return
+ break
}
c <- now
}
+ t.done <- true
}
// Tick is a convenience wrapper for NewTicker providing access to the ticking
@@ -73,7 +97,7 @@ func NewTicker(ns int64) *Ticker {
return nil
}
c := make(chan int64)
- t := &Ticker{c, ns, false}
+ t := &Ticker{c, make(chan bool), ns, false}
go t.ticker(c)
return t
}