1
0
mirror of https://github.com/golang/go synced 2024-11-22 06:04:39 -07:00

time: make tick.Stop a little more robust

R=r
CC=golang-dev, jackpal
https://golang.org/cl/186228
This commit is contained in:
Russ Cox 2010-01-19 17:46:21 -08:00
parent fe01d4c8a1
commit 1634b4236b

View File

@ -24,12 +24,26 @@ package time
// at intervals. // at intervals.
type Ticker struct { type Ticker struct {
C <-chan int64 // The channel on which the ticks are delivered. C <-chan int64 // The channel on which the ticks are delivered.
done chan bool
ns int64 ns int64
shutdown bool shutdown bool
} }
// Stop turns off a ticker. After Stop, no more ticks will be delivered. // Stop turns off a ticker. After Stop, no more ticks will be sent.
func (t *Ticker) Stop() { t.shutdown = true } 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) { func (t *Ticker) ticker(c chan<- int64) {
now := Nanoseconds() now := Nanoseconds()
@ -47,13 +61,23 @@ func (t *Ticker) ticker(c chan<- int64) {
when += t.ns when += t.ns
} }
Sleep(when - now) for !t.shutdown && when > now {
now = Nanoseconds() // 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 { if t.shutdown {
return break
} }
c <- now c <- now
} }
t.done <- true
} }
// Tick is a convenience wrapper for NewTicker providing access to the ticking // Tick is a convenience wrapper for NewTicker providing access to the ticking
@ -73,7 +97,7 @@ func NewTicker(ns int64) *Ticker {
return nil return nil
} }
c := make(chan int64) c := make(chan int64)
t := &Ticker{c, ns, false} t := &Ticker{c, make(chan bool), ns, false}
go t.ticker(c) go t.ticker(c)
return t return t
} }