mirror of
https://github.com/golang/go
synced 2024-11-26 16:57:14 -07:00
time: handle very large sleep durations
Fixes #4903. R=golang-dev, daniel.morsing, dave, r CC=golang-dev https://golang.org/cl/7388056
This commit is contained in:
parent
93158bf243
commit
89cf67eb20
@ -22,6 +22,21 @@ type runtimeTimer struct {
|
||||
arg interface{}
|
||||
}
|
||||
|
||||
// when is a helper function for setting the 'when' field of a runtimeTimer.
|
||||
// It returns what the time will be, in nanoseconds, Duration d in the future.
|
||||
// If d is negative, it is ignored. If the returned value would be less than
|
||||
// zero because of an overflow, MaxInt64 is returned.
|
||||
func when(d Duration) int64 {
|
||||
if d <= 0 {
|
||||
return nano()
|
||||
}
|
||||
t := nano() + int64(d)
|
||||
if t < 0 {
|
||||
t = 1<<63 - 1 // math.MaxInt64
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func startTimer(*runtimeTimer)
|
||||
func stopTimer(*runtimeTimer) bool
|
||||
|
||||
@ -49,7 +64,7 @@ func NewTimer(d Duration) *Timer {
|
||||
t := &Timer{
|
||||
C: c,
|
||||
r: runtimeTimer{
|
||||
when: nano() + int64(d),
|
||||
when: when(d),
|
||||
f: sendTime,
|
||||
arg: c,
|
||||
},
|
||||
@ -62,9 +77,9 @@ func NewTimer(d Duration) *Timer {
|
||||
// It returns true if the timer had been active, false if the timer had
|
||||
// expired or been stopped.
|
||||
func (t *Timer) Reset(d Duration) bool {
|
||||
when := nano() + int64(d)
|
||||
w := when(d)
|
||||
active := stopTimer(&t.r)
|
||||
t.r.when = when
|
||||
t.r.when = w
|
||||
startTimer(&t.r)
|
||||
return active
|
||||
}
|
||||
@ -94,7 +109,7 @@ func After(d Duration) <-chan Time {
|
||||
func AfterFunc(d Duration, f func()) *Timer {
|
||||
t := &Timer{
|
||||
r: runtimeTimer{
|
||||
when: nano() + int64(d),
|
||||
when: when(d),
|
||||
f: goFunc,
|
||||
arg: f,
|
||||
},
|
||||
|
@ -293,3 +293,23 @@ func TestReset(t *testing.T) {
|
||||
}
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Test that sleeping for an interval so large it overflows does not
|
||||
// result in a short sleep duration.
|
||||
func TestOverflowSleep(t *testing.T) {
|
||||
const timeout = 25 * Millisecond
|
||||
const big = Duration(int64(1<<63 - 1))
|
||||
select {
|
||||
case <-After(big):
|
||||
t.Fatalf("big timeout fired")
|
||||
case <-After(timeout):
|
||||
// OK
|
||||
}
|
||||
const neg = Duration(-1 << 63)
|
||||
select {
|
||||
case <-After(neg):
|
||||
// OK
|
||||
case <-After(timeout):
|
||||
t.Fatalf("negative timeout didn't fire")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user