Commit a71af254 authored by Andrew Gerrand's avatar Andrew Gerrand

time: warn about correct use of a Timer's Stop/Reset methods

Updates #14038
Fixes #14383

Change-Id: Icf6acb7c5d13ff1d3145084544c030a778482a38
Reviewed-on: https://go-review.googlesource.com/23575Reviewed-by: default avatarDmitry Vyukov <dvyukov@google.com>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent f9b4556d
...@@ -54,6 +54,14 @@ type Timer struct { ...@@ -54,6 +54,14 @@ type Timer struct {
// expired or been stopped. // expired or been stopped.
// Stop does not close the channel, to prevent a read from the channel succeeding // Stop does not close the channel, to prevent a read from the channel succeeding
// incorrectly. // incorrectly.
//
// To prevent the timer firing after a call to Stop,
// check the return value and drain the channel. For example:
// if !t.Stop() {
// <-t.C
// }
// This cannot be done concurrent to other receives from the Timer's
// channel.
func (t *Timer) Stop() bool { func (t *Timer) Stop() bool {
if t.r.f == nil { if t.r.f == nil {
panic("time: Stop called on uninitialized Timer") panic("time: Stop called on uninitialized Timer")
...@@ -80,6 +88,20 @@ func NewTimer(d Duration) *Timer { ...@@ -80,6 +88,20 @@ func NewTimer(d Duration) *Timer {
// Reset changes the timer to expire after duration d. // Reset changes the timer to expire after duration d.
// It returns true if the timer had been active, false if the timer had // It returns true if the timer had been active, false if the timer had
// expired or been stopped. // 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:
// 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.
// The return value exists to preserve compatibility with existing programs.
func (t *Timer) Reset(d Duration) bool { func (t *Timer) Reset(d Duration) bool {
if t.r.f == nil { if t.r.f == nil {
panic("time: Reset called on uninitialized Timer") panic("time: Reset called on uninitialized Timer")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment