forked from coocood/freecache
-
Notifications
You must be signed in to change notification settings - Fork 0
/
timer.go
79 lines (64 loc) · 1.55 KB
/
timer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package freecache
import (
"sync/atomic"
"time"
)
// Timer holds representation of current time.
type Timer interface {
// Give current time (in seconds)
Now() uint32
}
// Timer that must be stopped.
type StoppableTimer interface {
Timer
// Release resources of the timer, functionality may or may not be affected
// It is not called automatically, so user must call it just once
Stop()
}
// Helper function that returns Unix time in seconds
func getUnixTime() uint32 {
return uint32(time.Now().Unix())
}
// Default timer reads Unix time always when requested
type defaultTimer struct{}
func (timer defaultTimer) Now() uint32 {
return getUnixTime()
}
// Cached timer stores Unix time every second and returns the cached value
type cachedTimer struct {
now uint32
ticker *time.Ticker
done chan bool
}
// Create cached timer and start runtime timer that updates time every second
func NewCachedTimer() StoppableTimer {
timer := &cachedTimer{
now: getUnixTime(),
ticker: time.NewTicker(time.Second),
done: make(chan bool),
}
go timer.update()
return timer
}
func (timer *cachedTimer) Now() uint32 {
return atomic.LoadUint32(&timer.now)
}
// Stop runtime timer and finish routine that updates time
func (timer *cachedTimer) Stop() {
timer.ticker.Stop()
timer.done <- true
close(timer.done)
timer.done = nil
timer.ticker = nil
}
// Periodically check and update of time
func (timer *cachedTimer) update() {
for {
select {
case <-timer.done:
return
case <-timer.ticker.C:
atomic.StoreUint32(&timer.now, getUnixTime())
}
}
}