Coder Social home page Coder Social logo

timer's Introduction

Go Timer implementation with a fixed Reset behavior

GoDoc Go Report Card

This is a lightweight timer implementation which is a drop-in replacement for Go's Timer. Reset behaves as one would expect and drains the timer.C channel automatically. The core design of this package is similar to the original runtime timer implementation.

These two lines are equivalent except for saving some garbage:

t.Reset(x)

t := timer.NewTimer(x)

See issues:

Quote from the Timer Go doc reference:

Reset changes the timer to expire after duration d. 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: [...] 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.

Broken behavior sample

Sample 1

package main

import (
    "log"
    "time"
)

func main() {
	start := time.Now()

	// Start a new timer with a timeout of 1 second.
	timer := time.NewTimer(1 * time.Second)

	// Wait for 2 seconds.
	// Meanwhile the timer fired and filled the channel.
	time.Sleep(2 * time.Second)

	// Reset the timer. This should act exactly as creating a new timer.
	timer.Reset(1 * time.Second)

	// However this will fire immediately, because the channel was not drained.
	// See issue: https://github.com/golang/go/issues/11513
	<-timer.C

	if int(time.Since(start).Seconds()) != 3 {
		log.Fatalf("took ~%v seconds, should be ~3 seconds\n", int(time.Since(start).Seconds()))
	}
}

Sample 2

package main

import "time"

const (
	keepaliveInterval = 2 * time.Millisecond
)

var (
	resetC = make(chan struct{}, 1)
)

func main() {
	go keepaliveLoop()

	// Sample routine triggering the reset.
	// Example: this could be due to incoming peer requests and
	// a keepalive check should be reset to the max keepalive timeout.
	for i := 0; i < 1000; i++ {
		time.Sleep(time.Millisecond)
		resetKeepalive()
	}
}

func resetKeepalive() {
	// Don't block if there is already a reset request.
	select {
	case resetC <- struct{}{}:
	default:
	}
}

func keepaliveLoop() {
	t := time.NewTimer(keepaliveInterval)

	for {
		select {
		case <-resetC:
			time.Sleep(3 * time.Millisecond) // Simulate some reset work...
			t.Reset(keepaliveInterval)
		case <-t.C:
			ping()
			t.Reset(keepaliveInterval)
		}
	}
}

func ping() {
	panic("ping must not be called in this example")
}

timer's People

Contributors

r0l1 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.