Skip to content

Commit

Permalink
nobug: implement a safe timer function
Browse files Browse the repository at this point in the history
This PR adds libtime.SafeTimer function, which creates a timer that
is more safe to use in select statements, but without the overhead
of creating a context.Context object.

Instead it returns a StopFunc along with the time.Timer, forcing
the caller to deal with stopping the timer.
  • Loading branch information
shoenig committed Mar 14, 2022
1 parent ead4e18 commit a80e5a9
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 0 deletions.
36 changes: 36 additions & 0 deletions timer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package libtime

import (
"time"
)

// StopFunc is used to stop a time.Timer.
//
// Calling StopFunc prevents its time.Timer from firing. Returns true if the call
// stops the timer, false if the timer has already expired. or has been stopped.
//
// https://pkg.go.dev/time#Timer.Stop
type StopFunc func() bool

// SafeTimer creates a time.Timer and a StopFunc, forcing the caller to deal
// with the otherwise potential resource leak. Encourages safe use of a time.Timer
// in a select statement, but without the overhead of a context.Context.
//
// Typical usage:
//
// t, stop := libtime.SafeTimer(interval)
// defer stop()
// for {
// select {
// case <- t.C:
// foo()
// case <- otherC :
// return
// }
// }
//
// Does not panic if duration is <= 0, instead assuming the smallest positive value.
func SafeTimer(duration time.Duration) (*time.Timer, StopFunc) {
t := time.NewTimer(duration)
return t, t.Stop
}
20 changes: 20 additions & 0 deletions timer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package libtime

import (
"testing"
"time"

"github.com/stretchr/testify/require"
)

func Test_SafeTimer(t *testing.T) {
delay := 3 * time.Millisecond
start := time.Now()

timer, stop := SafeTimer(delay)
defer stop()
<-timer.C

elapsed := time.Since(start)
require.GreaterOrEqual(t, int64(elapsed), int64(delay))
}

0 comments on commit a80e5a9

Please sign in to comment.