Skip to content

Commit

Permalink
Add support for stopping timestamp updater
Browse files Browse the repository at this point in the history
  • Loading branch information
gaby committed Dec 16, 2024
1 parent 92e6848 commit 854a3e3
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 4 deletions.
24 changes: 20 additions & 4 deletions time.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
var (
timestampTimer sync.Once
timestamp uint32
stopChan chan struct{}
)

// Timestamp returns the current time.
Expand All @@ -21,16 +22,31 @@ 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(&timestamp, uint32(time.Now().Unix()))

stopChan = make(chan struct{})
go func(sleep time.Duration) {
ticker := time.NewTicker(sleep)
defer ticker.Stop()

for t := range ticker.C {
// update timestamp
atomic.StoreUint32(&timestamp, uint32(t.Unix()))
for {
select {
case t := <-ticker.C:
atomic.StoreUint32(&timestamp, uint32(t.Unix()))
case <-stopChan:
// Stop signal received, break the loop and exit goroutine
return
}
}
}(1 * time.Second) // duration
})
}

// StopTimeStampUpdater stops the currently running timestamp updater goroutine.
// This prevents leaking a goroutine if the updater is no longer needed.
func StopTimeStampUpdater() {
if stopChan != nil {
close(stopChan)
stopChan = nil
}
}
26 changes: 26 additions & 0 deletions time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ func Test_TimeStampUpdater(t *testing.T) {
checkTimeStamp(t, now+2, Timestamp())
}

func Test_StopTimeStampUpdater(t *testing.T) {
t.Parallel()

// Start the timestamp updater
StartTimeStampUpdater()

now := uint32(time.Now().Unix())
checkTimeStamp(t, now, Timestamp())

// Wait for an increment
time.Sleep(1 * time.Second)
checkTimeStamp(t, now+1, Timestamp())

// Stop the updater
StopTimeStampUpdater()

// Capture the timestamp after stopping
stoppedTime := Timestamp()

// Wait again to see if it updates
time.Sleep(2 * 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()
Expand Down

0 comments on commit 854a3e3

Please sign in to comment.