Hi Fabián,

The reason that this isn't working is because time.Ticker contains a 
runtimeTimer field:

    r: runtimeTimer{
        when:   when(d),
        period: int64(d),
        f:      sendTime,
        arg:    c,
    },

This corresponds with a struct defined in runtime:

    // Package time knows the layout of this structure.
    // If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
    // For GOOS=nacl, package syscall knows the layout of this structure.
    // If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
    type timer struct {
        i int // heap index

        // Timer wakes up at when, and then at when+period, ... (period > 0 
only)
        // each time calling f(arg, now) in the timer goroutine, so f must 
be
        // a well-behaved function and not block.
        when   int64
        period int64
        f      func(interface{}, uintptr)
        arg    interface{}
        seq    uintptr
    }

Notice that one of the fields is the heap index. When the runtime timer is 
initialized that heap index is set like this:

    t.i = len(timers.t)

And, crucially, it's updated anytime timers are added or removed:

    if i != last {
        timers.t[i] = timers.t[last]
        timers.t[i].i = i
    }

When you dereferenced the Ticker pointer, you made a copy of the this 
struct. This meant that those updates to the heap index weren't happening 
to your copy, but only the original struct. When you then tried to remove 
the timer, it had the wrong index.

- Caleb

On Friday, April 14, 2017 at 1:11:41 AM UTC-4, Fabián Inostroza wrote:
>
> Hi,
>
> I'm writing and application where I need to check for some condition and 
> do something every 'x' < 'y' seconds. If the condition is not true after 
> 'y' seconds I do something. Every time the condition checked every 'x' 
> seconds is true I have to reset the 'y' timeout.
>
> I wrote a test application based on code found in 
> https://medium.com/@arpith/resetting-a-ticker-in-go-63858a2c17ec
> package main
>
> import "time"
>
> // Ticker asdf
> type Ticker struct {
>     period time.Duration
>     ticker time.Ticker
> }
>
> func createTicker(period time.Duration) *Ticker {
>     return &Ticker{period, *time.NewTicker(period)}
> }
>
> func (t *Ticker) resetTicker() {
>     t.ticker.Stop()
>     t.ticker = *time.NewTicker(t.period)
> }
>
> type timers struct {
>     ticker1 Ticker
>     ticker2 Ticker
>     done    chan bool
> }
>
> func (t *timers) work() {
>     condition := true
>     count := 0
>     for {
>         select {
>         case <-t.ticker1.ticker.C:
>             if condition {
>                 if count >= 5 {
>                     count = 0
>                     condition = false
>                 } else {
>                     t.ticker2.resetTicker()
>                     count++
>                 }
>             }
>         case <-t.ticker2.ticker.C:
>             if count >= 2 {
>                 count = 0
>                 condition = true
>             }
>             count++
>         case <-t.done:
>             return
>         }
>     }
> }
>
> func createPeriodicTask() *timers {
>     ticker1 := createTicker(time.Duration(5) * time.Second)
>     ticker2 := createTicker(time.Duration(1) * time.Minute)
>     quit := make(chan bool)
>
>     timer := timers{*ticker1, *ticker2, quit}
>     return &timer
> }
>
> func main() {
>     timersArray := make([]*timers, 1000)
>
>     for i := range timersArray {
>         timer := createPeriodicTask()
>         timersArray[i] = timer
>         go timer.work()
>     }
>
>     //m := runtime.MemStats{}
>     for {
>         for i := range timersArray {
>             select {
>             case <-timersArray[i].done:
>                 break
>             default:
>                 time.Sleep(time.Duration(2000) * time.Millisecond)
>                 //fmt.Println("Numero de goroutines existentes: ", 
> runtime.NumGoroutine())
>                 //runtime.ReadMemStats(&m)
>                 //fmt.Printf("%+v\n", m)
>             }
>         }
>     }
> }
>
>
> If I run this program for many hours the memory usage of the process 
> steadily increases.
>
> I changed the Ticker struct definition to use pointers to the 
> time.newTicker and the problem is gone but I don't understand what was 
> wrong with the first version, could somebody give me a hint?
>

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to