diff --git a/time.go b/time.go index 4dfdfe4..ddd8856 100644 --- a/time.go +++ b/time.go @@ -9,6 +9,7 @@ import ( var ( timestampTimer sync.Once timestamp uint32 + stopChan chan struct{} ) // Timestamp returns the current time. @@ -21,16 +22,32 @@ func Timestamp() uint32 { // which is much better for performance than determining it at runtime each time func StartTimeStampUpdater() { timestampTimer.Do(func() { - // set initial value atomic.StoreUint32(×tamp, uint32(time.Now().Unix())) - go func(sleep time.Duration) { + + c := make(chan struct{}) + stopChan = c + + go func(localChan chan struct{}, sleep time.Duration) { ticker := time.NewTicker(sleep) defer ticker.Stop() - for t := range ticker.C { - // update timestamp - atomic.StoreUint32(×tamp, uint32(t.Unix())) + for { + select { + case t := <-ticker.C: + atomic.StoreUint32(×tamp, uint32(t.Unix())) + case <-localChan: + return + } } - }(1 * time.Second) // duration + }(c, 1*time.Second) }) } + +// StopTimeStampUpdater stops the timestamp updater +// WARNING: Make sure to call this function before the program exits, otherwise it will leak goroutines +func StopTimeStampUpdater() { + if stopChan != nil { + close(stopChan) + stopChan = nil + } +} diff --git a/time_test.go b/time_test.go index 2b41ff6..ca74ffa 100644 --- a/time_test.go +++ b/time_test.go @@ -14,8 +14,6 @@ func checkTimeStamp(tb testing.TB, expectedCurrent, actualCurrent uint32) { } func Test_TimeStampUpdater(t *testing.T) { - t.Parallel() - StartTimeStampUpdater() now := uint32(time.Now().Unix()) @@ -30,6 +28,22 @@ func Test_TimeStampUpdater(t *testing.T) { checkTimeStamp(t, now+2, Timestamp()) } +func Test_StopTimeStampUpdater(t *testing.T) { + // Start the timestamp updater + StartTimeStampUpdater() + + // Stop the updater + StopTimeStampUpdater() + + // Capture the timestamp after stopping + stoppedTime := Timestamp() + + // Wait before checking the timestamp + time.Sleep(5 * time.Second) + // It should not have changed since we've stopped the updater + require.Equal(t, stoppedTime, Timestamp(), "timestamp should not change after stopping updater") +} + func Benchmark_CalculateTimestamp(b *testing.B) { var res uint32 StartTimeStampUpdater()