Difference between time.NewTimer() and time.Reset() when "clear" timer

1,988 views
Skip to first unread message

fdin...@gmail.com

unread,
Apr 17, 2016, 10:29:25 AM4/17/16
to golang-nuts
Hi all:

I am writing something as a watch-dog, for example, a timer will be reseted to timing from 0 if something happened, otherwise after a const duration, it will timeout.

To re-timing the timer, there maybe 2 ways:

tmr := time.NewTimer(d)

// watcher
for {
   
select {
   
case <- tmr.C:
       
// timeout! blablabla..
   
   
case <- something-happened-notice-channel:
       
// 2 ways to reset timer:
       
// tmr.Reset(d)
       
// tmr = time.NewTimer(d)
   
}
}


These 2 different ways to reset timer seems do the same thing, except the latest is more expensive because of allocating new memory and may trigger GC-handling more frequently than the 1st way, especially when a huge amount of timer is allocated (this is just what I thought, maybe incorrect, please tell me more if anyone know the details).

But when I use it in my code, these 2 ways leads my code to different result. My related function is:

func (rf *Raft) newRandTimer() {
    rf
.timeout = electionTimeoutGen()
   
/*
    if rf.timer == nil {
        rf.timer = time.NewTimer(rf.timeout)
    } else {
        rf.timer.Reset(rf.timeout)
    }
    */

    rf
.timer = time.NewTimer(rf.timeout)
}


When I use code in /* */, it cannot reset the timer and will expired, which is not correct, however, when I code as re-allocate timer, it goes well. Any tips please?

Thanks.

pierre...@gmail.com

unread,
Apr 17, 2016, 1:11:06 PM4/17/16
to golang-nuts, fdin...@gmail.com
Hello,

You should definitely use the Reset() method.

Using the first code sample you provided, everything works as expected, see http://play.golang.org/p/Zq50IYFPTO.

I am not sure why it fails in your full code, maybe try to isolate a non-working as expected sample?

roger peppe

unread,
Apr 18, 2016, 3:36:45 AM4/18/16
to Pierre Curto, golang-nuts, fdin...@gmail.com
Timer.Reset has unfortunate semantics and is awkward to use correctly.
Notably, calling Reset does not guarantee that you won't
receive a value on the channel from the last timer event.

You might find it worthwhile to read this thread:

https://groups.google.com/forum/#!topic/golang-dev/c9UUfASVPoU

and these issues:

https://github.com/golang/go/issues/11513
https://github.com/golang/go/issues/14038

In summary, you shouldn't call Timer.Reset without
checking its return value and receiving from the channel
if it returned false.

cheers,
rog.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages