-
Notifications
You must be signed in to change notification settings - Fork 5
/
funcs.go
63 lines (48 loc) · 2.25 KB
/
funcs.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
// +build !timex_disable
package timex
import (
"sync"
"sync/atomic"
"time"
)
// Now can be used as a replacement of time.Now()
func Now() time.Time { return impl.Load().(Implementation).Now() }
// Since can be used as a replacement of time.Since()
func Since(t time.Time) time.Duration { return impl.Load().(Implementation).Since(t) }
// Until can be used as a replacement of time.Until()
func Until(t time.Time) time.Duration { return impl.Load().(Implementation).Until(t) }
// Sleep can be used as a replacement of time.Sleep()
func Sleep(d time.Duration) { impl.Load().(Implementation).Sleep(d) }
// After can be used a replacement of time.After()
func After(d time.Duration) <-chan time.Time { return impl.Load().(Implementation).After(d) }
// AfterFunc can be used as a replacement of time.AfterFunc()
func AfterFunc(d time.Duration, f func()) Timer { return impl.Load().(Implementation).AfterFunc(d, f) }
// NewTicker creates a new ticker as a replacement of time.NewTicker
func NewTicker(d time.Duration) Ticker { return impl.Load().(Implementation).NewTicker(d) }
// NewTimer creates a new timer as a replacement of time.NewTimer
func NewTimer(d time.Duration) Timer { return impl.Load().(Implementation).NewTimer(d) }
// overridden is a lock we take when we override the timex implementation
// since golang packages can run tests in different packages concurrently,
// we want to make sure that there are no two implementations overriding
// concurrently
// https://medium.com/@xcoulon/how-to-avoid-parallel-execution-of-tests-in-golang-763d32d88eec
var overridden sync.Mutex
// Override replaces the global implementation used for timex
// The returned function should be called to restore the default implementation
func Override(implementation Implementation) func() {
overridden.Lock()
impl.Store(implValue{implementation})
return func() {
impl.Store(implValue{Default{}})
overridden.Unlock()
}
}
// impl stores the current implementation being used
// we don't use the RWMutex to read the impl itself because atomic.Value is faster
// in a _frequent read - unfrequent write_ scenario according to the docs
// https://tip.golang.org/pkg/sync/atomic/#Value
var impl atomic.Value
type implValue struct{ Implementation }
func init() {
impl.Store(implValue{Default{}})
}