1
0
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:
Andrew Gerrand 2013-02-26 09:23:58 +11:00
parent 93158bf243
commit 89cf67eb20
2 changed files with 39 additions and 4 deletions

View File

@ -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,
},

View File

@ -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")
}
}