goticker

Ticker should not execute if already running


I have some function that has to run periodically. I have used a ticker for this. But if the ticker is already running, and the time interval passes again, it should not execute again.

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(3*time.Second)
    flag := 0
    defer ticker.Stop()
    for {
        select {
        case t := <-ticker.C:
            flag = flag + 1
            if (flag % 2 ==0 ) {
                time.Sleep(time.Second*4)
            }   
            fmt.Println("Current time: ", t)
        }
    }
}

https://play.golang.org/p/2xV2MYInn4I

In the playground, the ticker prints every 3 seconds, but every even turn of the ticker the job takes more time than the interval. I expect it to not run then and drop those ticks.

How do I do this?


Solution

  • sleeping inside the same goroutine merely delays execution. ticker meanwhile runs in a separate goroutine. So even if you used a global variable to maintain an execution state - it will not give you your desired result with sleep. However migrating the whole "sleeping" in a separate goroutine yields:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    type Tick struct {
        ticker *time.Ticker
        executing bool
    }
    
    func somethingYouWantToDo(tick *Tick, flag *int, t time.Time) {
        if tick.executing {
            return
        }
    
        tick.executing = true
    
        *flag = *flag + 1
    
        if (*flag % 2 ==0 ) {
                    time.Sleep(time.Second*4)
        }   
            fmt.Println("Current time: ", t)
        tick.executing = false
    }
    
    func main() {
        tick := &Tick{
            ticker: time.NewTicker(3*time.Second),
        }
        flag := 0
        defer tick.ticker.Stop()
        for {
            select {
            case t := <-tick.ticker.C:
                go somethingYouWantToDo(tick, &flag, t)
            }
        }
    }
    // output
    // Current time:  2009-11-10 23:00:03 +0000 UTC m=+3.000000001
    // Current time:  2009-11-10 23:00:06 +0000 UTC m=+6.000000001
    // Current time:  2009-11-10 23:00:12 +0000 UTC m=+12.000000001
    // Current time:  2009-11-10 23:00:15 +0000 UTC m=+15.000000001
    // Current time:  2009-11-10 23:00:21 +0000 UTC m=+21.000000001
    // Current time:  2009-11-10 23:00:24 +0000 UTC m=+24.000000001
    // Current time:  2009-11-10 23:00:30 +0000 UTC m=+30.000000001
    // Current time:  2009-11-10 23:00:33 +0000 UTC m=+33.000000001
    // Current time:  2009-11-10 23:00:39 +0000 UTC m=+39.000000001
    // Current time:  2009-11-10 23:00:42 +0000 UTC m=+42.000000001
    // Current time:  2009-11-10 23:00:48 +0000 UTC m=+48.000000001
    // Current time:  2009-11-10 23:00:51 +0000 UTC m=+51.000000001
    // Current time:  2009-11-10 23:00:57 +0000 UTC m=+57.000000001
    // Current time:  2009-11-10 23:01:00 +0000 UTC m=+60.000000001
    // Current time:  2009-11-10 23:01:06 +0000 UTC m=+66.000000001
    // Current time:  2009-11-10 23:01:09 +0000 UTC m=+69.000000001
    

    Try it on the playground