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
t := &Timer{
C: c,
r: runtimeTimer{
- when: nano() + int64(d),
+ when: when(d),
f: sendTime,
arg: c,
},
// 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
}
func AfterFunc(d Duration, f func()) *Timer {
t := &Timer{
r: runtimeTimer{
- when: nano() + int64(d),
+ when: when(d),
f: goFunc,
arg: f,
},
}
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")
+ }
+}