summaryrefslogtreecommitdiff
path: root/libgo/go/time/sleep.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/time/sleep.go')
-rw-r--r--libgo/go/time/sleep.go28
1 files changed, 22 insertions, 6 deletions
diff --git a/libgo/go/time/sleep.go b/libgo/go/time/sleep.go
index 73114f5eecd..4b01404896e 100644
--- a/libgo/go/time/sleep.go
+++ b/libgo/go/time/sleep.go
@@ -12,7 +12,7 @@ func Sleep(d Duration)
func runtimeNano() int64
// Interface to timers implemented in package runtime.
-// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
+// Must be in sync with ../runtime/time.go:/^type timer
type runtimeTimer struct {
i int
when int64
@@ -55,13 +55,22 @@ type Timer struct {
// Stop does not close the channel, to prevent a read from the channel succeeding
// incorrectly.
//
-// To prevent the timer firing after a call to Stop,
-// check the return value and drain the channel. For example:
+// To prevent a timer created with NewTimer from firing after a call to Stop,
+// check the return value and drain the channel.
+// For example, assuming the program has not received from t.C already:
+//
// if !t.Stop() {
// <-t.C
// }
+//
// This cannot be done concurrent to other receives from the Timer's
// channel.
+//
+// For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
+// has already expired and the function f has been started in its own goroutine;
+// Stop does not wait for f to complete before returning.
+// If the caller needs to know whether f is completed, it must coordinate
+// with f explicitly.
func (t *Timer) Stop() bool {
if t.r.f == nil {
panic("time: Stop called on uninitialized Timer")
@@ -89,18 +98,25 @@ func NewTimer(d Duration) *Timer {
// It returns true if the timer had been active, false if the timer had
// expired or been stopped.
//
-// To reuse an active timer, always call its Stop method first and—if it had
-// expired—drain the value from its channel. For example:
+// Resetting a timer must take care not to race with the send into t.C
+// that happens when the current timer expires.
+// If a program has already received a value from t.C, the timer is known
+// to have expired, and t.Reset can be used directly.
+// If a program has not yet received a value from t.C, however,
+// the timer must be stopped and—if Stop reports that the timer expired
+// before being stopped—the channel explicitly drained:
+//
// if !t.Stop() {
// <-t.C
// }
// t.Reset(d)
+//
// This should not be done concurrent to other receives from the Timer's
// channel.
//
// Note that it is not possible to use Reset's return value correctly, as there
// is a race condition between draining the channel and the new timer expiring.
-// Reset should always be used in concert with Stop, as described above.
+// Reset should always be invoked on stopped or expired channels, as described above.
// The return value exists to preserve compatibility with existing programs.
func (t *Timer) Reset(d Duration) bool {
if t.r.f == nil {