mirror of
https://github.com/golang/go
synced 2024-11-22 01:04:40 -07:00
time.Ticker: fix bug arising when all tickers are dead.
thanks to yglgogo for analysis. Fixes #593. R=rsc CC=golang-dev https://golang.org/cl/210044
This commit is contained in:
parent
3dc04f4a22
commit
7b76175a1c
@ -39,16 +39,23 @@ type alarmer struct {
|
|||||||
|
|
||||||
// Set alarm to go off at time ns, if not already set earlier.
|
// Set alarm to go off at time ns, if not already set earlier.
|
||||||
func (a *alarmer) set(ns int64) {
|
func (a *alarmer) set(ns int64) {
|
||||||
// If there's no wakeLoop or the next tick we expect is too late, start a new wakeLoop
|
switch {
|
||||||
if a.wakeMeAt == nil || a.wakeTime > ns {
|
case a.wakeTime > ns:
|
||||||
// Stop previous wakeLoop.
|
// Next tick we expect is too late; shut down the late runner
|
||||||
if a.wakeMeAt != nil {
|
// and (after fallthrough) start a new wakeLoop.
|
||||||
a.wakeMeAt <- -1
|
a.wakeMeAt <- -1
|
||||||
}
|
fallthrough
|
||||||
|
case a.wakeMeAt == nil:
|
||||||
|
// There's no wakeLoop, start one.
|
||||||
a.wakeMeAt = make(chan int64, 10)
|
a.wakeMeAt = make(chan int64, 10)
|
||||||
go wakeLoop(a.wakeMeAt, a.wakeUp)
|
go wakeLoop(a.wakeMeAt, a.wakeUp)
|
||||||
|
fallthrough
|
||||||
|
case a.wakeTime == 0:
|
||||||
|
// Nobody else is waiting; it's just us.
|
||||||
a.wakeTime = ns
|
a.wakeTime = ns
|
||||||
a.wakeMeAt <- ns
|
a.wakeMeAt <- ns
|
||||||
|
default:
|
||||||
|
// There's already someone scheduled.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +148,8 @@ func tickerLoop() {
|
|||||||
// Please send wakeup at earliest required time.
|
// Please send wakeup at earliest required time.
|
||||||
// If there are no tickers, don't bother.
|
// If there are no tickers, don't bother.
|
||||||
alarm.wakeMeAt <- wakeTime
|
alarm.wakeMeAt <- wakeTime
|
||||||
|
} else {
|
||||||
|
alarm.wakeTime = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevTime = now
|
prevTime = now
|
||||||
|
@ -34,3 +34,12 @@ func TestTicker(t *testing.T) {
|
|||||||
t.Fatalf("Ticker did not shut down")
|
t.Fatalf("Ticker did not shut down")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that a bug tearing down a ticker has been fixed. This routine should not deadlock.
|
||||||
|
func TestTeardown(t *testing.T) {
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
ticker := NewTicker(1e8)
|
||||||
|
<-ticker.C
|
||||||
|
ticker.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user