clock.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package clock
  15. import (
  16. "sync"
  17. "time"
  18. )
  19. // Clock allows for injecting fake or real clocks into code that
  20. // needs to do arbitrary things based on time.
  21. type Clock interface {
  22. Now() time.Time
  23. Since(time.Time) time.Duration
  24. After(d time.Duration) <-chan time.Time
  25. NewTimer(d time.Duration) Timer
  26. Sleep(d time.Duration)
  27. Tick(d time.Duration) <-chan time.Time
  28. }
  29. var (
  30. _ = Clock(RealClock{})
  31. _ = Clock(&FakeClock{})
  32. _ = Clock(&IntervalClock{})
  33. )
  34. // RealClock really calls time.Now()
  35. type RealClock struct{}
  36. // Now returns the current time.
  37. func (RealClock) Now() time.Time {
  38. return time.Now()
  39. }
  40. // Since returns time since the specified timestamp.
  41. func (RealClock) Since(ts time.Time) time.Duration {
  42. return time.Since(ts)
  43. }
  44. // Same as time.After(d).
  45. func (RealClock) After(d time.Duration) <-chan time.Time {
  46. return time.After(d)
  47. }
  48. func (RealClock) NewTimer(d time.Duration) Timer {
  49. return &realTimer{
  50. timer: time.NewTimer(d),
  51. }
  52. }
  53. func (RealClock) Tick(d time.Duration) <-chan time.Time {
  54. return time.Tick(d)
  55. }
  56. func (RealClock) Sleep(d time.Duration) {
  57. time.Sleep(d)
  58. }
  59. // FakeClock implements Clock, but returns an arbitrary time.
  60. type FakeClock struct {
  61. lock sync.RWMutex
  62. time time.Time
  63. // waiters are waiting for the fake time to pass their specified time
  64. waiters []fakeClockWaiter
  65. }
  66. type fakeClockWaiter struct {
  67. targetTime time.Time
  68. stepInterval time.Duration
  69. skipIfBlocked bool
  70. destChan chan time.Time
  71. fired bool
  72. }
  73. func NewFakeClock(t time.Time) *FakeClock {
  74. return &FakeClock{
  75. time: t,
  76. }
  77. }
  78. // Now returns f's time.
  79. func (f *FakeClock) Now() time.Time {
  80. f.lock.RLock()
  81. defer f.lock.RUnlock()
  82. return f.time
  83. }
  84. // Since returns time since the time in f.
  85. func (f *FakeClock) Since(ts time.Time) time.Duration {
  86. f.lock.RLock()
  87. defer f.lock.RUnlock()
  88. return f.time.Sub(ts)
  89. }
  90. // Fake version of time.After(d).
  91. func (f *FakeClock) After(d time.Duration) <-chan time.Time {
  92. f.lock.Lock()
  93. defer f.lock.Unlock()
  94. stopTime := f.time.Add(d)
  95. ch := make(chan time.Time, 1) // Don't block!
  96. f.waiters = append(f.waiters, fakeClockWaiter{
  97. targetTime: stopTime,
  98. destChan: ch,
  99. })
  100. return ch
  101. }
  102. // Fake version of time.NewTimer(d).
  103. func (f *FakeClock) NewTimer(d time.Duration) Timer {
  104. f.lock.Lock()
  105. defer f.lock.Unlock()
  106. stopTime := f.time.Add(d)
  107. ch := make(chan time.Time, 1) // Don't block!
  108. timer := &fakeTimer{
  109. fakeClock: f,
  110. waiter: fakeClockWaiter{
  111. targetTime: stopTime,
  112. destChan: ch,
  113. },
  114. }
  115. f.waiters = append(f.waiters, timer.waiter)
  116. return timer
  117. }
  118. func (f *FakeClock) Tick(d time.Duration) <-chan time.Time {
  119. f.lock.Lock()
  120. defer f.lock.Unlock()
  121. tickTime := f.time.Add(d)
  122. ch := make(chan time.Time, 1) // hold one tick
  123. f.waiters = append(f.waiters, fakeClockWaiter{
  124. targetTime: tickTime,
  125. stepInterval: d,
  126. skipIfBlocked: true,
  127. destChan: ch,
  128. })
  129. return ch
  130. }
  131. // Move clock by Duration, notify anyone that's called After, Tick, or NewTimer
  132. func (f *FakeClock) Step(d time.Duration) {
  133. f.lock.Lock()
  134. defer f.lock.Unlock()
  135. f.setTimeLocked(f.time.Add(d))
  136. }
  137. // Sets the time.
  138. func (f *FakeClock) SetTime(t time.Time) {
  139. f.lock.Lock()
  140. defer f.lock.Unlock()
  141. f.setTimeLocked(t)
  142. }
  143. // Actually changes the time and checks any waiters. f must be write-locked.
  144. func (f *FakeClock) setTimeLocked(t time.Time) {
  145. f.time = t
  146. newWaiters := make([]fakeClockWaiter, 0, len(f.waiters))
  147. for i := range f.waiters {
  148. w := &f.waiters[i]
  149. if !w.targetTime.After(t) {
  150. if w.skipIfBlocked {
  151. select {
  152. case w.destChan <- t:
  153. w.fired = true
  154. default:
  155. }
  156. } else {
  157. w.destChan <- t
  158. w.fired = true
  159. }
  160. if w.stepInterval > 0 {
  161. for !w.targetTime.After(t) {
  162. w.targetTime = w.targetTime.Add(w.stepInterval)
  163. }
  164. newWaiters = append(newWaiters, *w)
  165. }
  166. } else {
  167. newWaiters = append(newWaiters, f.waiters[i])
  168. }
  169. }
  170. f.waiters = newWaiters
  171. }
  172. // Returns true if After has been called on f but not yet satisfied (so you can
  173. // write race-free tests).
  174. func (f *FakeClock) HasWaiters() bool {
  175. f.lock.RLock()
  176. defer f.lock.RUnlock()
  177. return len(f.waiters) > 0
  178. }
  179. func (f *FakeClock) Sleep(d time.Duration) {
  180. f.Step(d)
  181. }
  182. // IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration
  183. type IntervalClock struct {
  184. Time time.Time
  185. Duration time.Duration
  186. }
  187. // Now returns i's time.
  188. func (i *IntervalClock) Now() time.Time {
  189. i.Time = i.Time.Add(i.Duration)
  190. return i.Time
  191. }
  192. // Since returns time since the time in i.
  193. func (i *IntervalClock) Since(ts time.Time) time.Duration {
  194. return i.Time.Sub(ts)
  195. }
  196. // Unimplemented, will panic.
  197. // TODO: make interval clock use FakeClock so this can be implemented.
  198. func (*IntervalClock) After(d time.Duration) <-chan time.Time {
  199. panic("IntervalClock doesn't implement After")
  200. }
  201. // Unimplemented, will panic.
  202. // TODO: make interval clock use FakeClock so this can be implemented.
  203. func (*IntervalClock) NewTimer(d time.Duration) Timer {
  204. panic("IntervalClock doesn't implement NewTimer")
  205. }
  206. // Unimplemented, will panic.
  207. // TODO: make interval clock use FakeClock so this can be implemented.
  208. func (*IntervalClock) Tick(d time.Duration) <-chan time.Time {
  209. panic("IntervalClock doesn't implement Tick")
  210. }
  211. func (*IntervalClock) Sleep(d time.Duration) {
  212. panic("IntervalClock doesn't implement Sleep")
  213. }
  214. // Timer allows for injecting fake or real timers into code that
  215. // needs to do arbitrary things based on time.
  216. type Timer interface {
  217. C() <-chan time.Time
  218. Stop() bool
  219. Reset(d time.Duration) bool
  220. }
  221. var (
  222. _ = Timer(&realTimer{})
  223. _ = Timer(&fakeTimer{})
  224. )
  225. // realTimer is backed by an actual time.Timer.
  226. type realTimer struct {
  227. timer *time.Timer
  228. }
  229. // C returns the underlying timer's channel.
  230. func (r *realTimer) C() <-chan time.Time {
  231. return r.timer.C
  232. }
  233. // Stop calls Stop() on the underlying timer.
  234. func (r *realTimer) Stop() bool {
  235. return r.timer.Stop()
  236. }
  237. // Reset calls Reset() on the underlying timer.
  238. func (r *realTimer) Reset(d time.Duration) bool {
  239. return r.timer.Reset(d)
  240. }
  241. // fakeTimer implements Timer based on a FakeClock.
  242. type fakeTimer struct {
  243. fakeClock *FakeClock
  244. waiter fakeClockWaiter
  245. }
  246. // C returns the channel that notifies when this timer has fired.
  247. func (f *fakeTimer) C() <-chan time.Time {
  248. return f.waiter.destChan
  249. }
  250. // Stop stops the timer and returns true if the timer has not yet fired, or false otherwise.
  251. func (f *fakeTimer) Stop() bool {
  252. f.fakeClock.lock.Lock()
  253. defer f.fakeClock.lock.Unlock()
  254. newWaiters := make([]fakeClockWaiter, 0, len(f.fakeClock.waiters))
  255. for i := range f.fakeClock.waiters {
  256. w := &f.fakeClock.waiters[i]
  257. if w != &f.waiter {
  258. newWaiters = append(newWaiters, *w)
  259. }
  260. }
  261. f.fakeClock.waiters = newWaiters
  262. return !f.waiter.fired
  263. }
  264. // Reset resets the timer to the fake clock's "now" + d. It returns true if the timer has not yet
  265. // fired, or false otherwise.
  266. func (f *fakeTimer) Reset(d time.Duration) bool {
  267. f.fakeClock.lock.Lock()
  268. defer f.fakeClock.lock.Unlock()
  269. active := !f.waiter.fired
  270. f.waiter.fired = false
  271. f.waiter.targetTime = f.fakeClock.time.Add(d)
  272. return active
  273. }