summaryrefslogtreecommitdiff
path: root/src/pkg/time/sleep.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/time/sleep.go')
-rw-r--r--src/pkg/time/sleep.go38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/pkg/time/sleep.go b/src/pkg/time/sleep.go
index 27820b0ea..591fa27b0 100644
--- a/src/pkg/time/sleep.go
+++ b/src/pkg/time/sleep.go
@@ -18,10 +18,25 @@ type runtimeTimer struct {
i int32
when int64
period int64
- f func(int64, interface{})
+ f func(int64, interface{}) // NOTE: must not be closure
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
@@ -35,8 +50,10 @@ type Timer struct {
// Stop prevents the Timer from firing.
// It returns true if the call stops the timer, false if the timer has already
-// expired or stopped.
-func (t *Timer) Stop() (ok bool) {
+// expired or been stopped.
+// Stop does not close the channel, to prevent a read from the channel succeeding
+// incorrectly.
+func (t *Timer) Stop() bool {
return stopTimer(&t.r)
}
@@ -47,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,
},
@@ -56,6 +73,17 @@ func NewTimer(d Duration) *Timer {
return t
}
+// Reset changes the timer to expire after duration d.
+// 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 {
+ w := when(d)
+ active := stopTimer(&t.r)
+ t.r.when = w
+ startTimer(&t.r)
+ return active
+}
+
func sendTime(now int64, c interface{}) {
// Non-blocking send of time on c.
// Used in NewTimer, it cannot block anyway (buffer).
@@ -81,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,
},