clock.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. /*
  2. Copyright 2014 The Kubernetes Authors.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package clock
  14. import (
  15. "sync"
  16. "time"
  17. )
  18. // PassiveClock allows for injecting fake or real clocks into code
  19. // that needs to read the current time but does not support scheduling
  20. // activity in the future.
  21. type PassiveClock interface {
  22. Now() time.Time
  23. Since(time.Time) time.Duration
  24. }
  25. // Clock allows for injecting fake or real clocks into code that
  26. // needs to do arbitrary things based on time.
  27. type Clock interface {
  28. PassiveClock
  29. After(time.Duration) <-chan time.Time
  30. AfterFunc(time.Duration, func()) Timer
  31. NewTimer(time.Duration) Timer
  32. Sleep(time.Duration)
  33. NewTicker(time.Duration) Ticker
  34. }
  35. // RealClock really calls time.Now()
  36. type RealClock struct{}
  37. // Now returns the current time.
  38. func (RealClock) Now() time.Time {
  39. return time.Now()
  40. }
  41. // Since returns time since the specified timestamp.
  42. func (RealClock) Since(ts time.Time) time.Duration {
  43. return time.Since(ts)
  44. }
  45. // After is the same as time.After(d).
  46. func (RealClock) After(d time.Duration) <-chan time.Time {
  47. return time.After(d)
  48. }
  49. // AfterFunc is the same as time.AfterFunc(d, f).
  50. func (RealClock) AfterFunc(d time.Duration, f func()) Timer {
  51. return &realTimer{
  52. timer: time.AfterFunc(d, f),
  53. }
  54. }
  55. // NewTimer returns a new Timer.
  56. func (RealClock) NewTimer(d time.Duration) Timer {
  57. return &realTimer{
  58. timer: time.NewTimer(d),
  59. }
  60. }
  61. // NewTicker returns a new Ticker.
  62. func (RealClock) NewTicker(d time.Duration) Ticker {
  63. return &realTicker{
  64. ticker: time.NewTicker(d),
  65. }
  66. }
  67. // Sleep pauses the RealClock for duration d.
  68. func (RealClock) Sleep(d time.Duration) {
  69. time.Sleep(d)
  70. }
  71. // FakePassiveClock implements PassiveClock, but returns an arbitrary time.
  72. type FakePassiveClock struct {
  73. lock sync.RWMutex
  74. time time.Time
  75. }
  76. // FakeClock implements Clock, but returns an arbitrary time.
  77. type FakeClock struct {
  78. FakePassiveClock
  79. // waiters are waiting for the fake time to pass their specified time
  80. waiters []fakeClockWaiter
  81. }
  82. type fakeClockWaiter struct {
  83. targetTime time.Time
  84. stepInterval time.Duration
  85. skipIfBlocked bool
  86. destChan chan time.Time
  87. afterFunc func()
  88. }
  89. // NewFakePassiveClock returns a new FakePassiveClock.
  90. func NewFakePassiveClock(t time.Time) *FakePassiveClock {
  91. return &FakePassiveClock{
  92. time: t,
  93. }
  94. }
  95. // NewFakeClock returns a new FakeClock
  96. func NewFakeClock(t time.Time) *FakeClock {
  97. return &FakeClock{
  98. FakePassiveClock: *NewFakePassiveClock(t),
  99. }
  100. }
  101. // Now returns f's time.
  102. func (f *FakePassiveClock) Now() time.Time {
  103. f.lock.RLock()
  104. defer f.lock.RUnlock()
  105. return f.time
  106. }
  107. // Since returns time since the time in f.
  108. func (f *FakePassiveClock) Since(ts time.Time) time.Duration {
  109. f.lock.RLock()
  110. defer f.lock.RUnlock()
  111. return f.time.Sub(ts)
  112. }
  113. // SetTime sets the time on the FakePassiveClock.
  114. func (f *FakePassiveClock) SetTime(t time.Time) {
  115. f.lock.Lock()
  116. defer f.lock.Unlock()
  117. f.time = t
  118. }
  119. // After is the Fake version of time.After(d).
  120. func (f *FakeClock) After(d time.Duration) <-chan time.Time {
  121. f.lock.Lock()
  122. defer f.lock.Unlock()
  123. stopTime := f.time.Add(d)
  124. ch := make(chan time.Time, 1) // Don't block!
  125. f.waiters = append(f.waiters, fakeClockWaiter{
  126. targetTime: stopTime,
  127. destChan: ch,
  128. })
  129. return ch
  130. }
  131. // AfterFunc is the Fake version of time.AfterFunc(d, callback).
  132. func (f *FakeClock) AfterFunc(d time.Duration, cb func()) Timer {
  133. f.lock.Lock()
  134. defer f.lock.Unlock()
  135. stopTime := f.time.Add(d)
  136. ch := make(chan time.Time, 1) // Don't block!
  137. timer := &fakeTimer{
  138. fakeClock: f,
  139. waiter: fakeClockWaiter{
  140. targetTime: stopTime,
  141. destChan: ch,
  142. afterFunc: cb,
  143. },
  144. }
  145. f.waiters = append(f.waiters, timer.waiter)
  146. return timer
  147. }
  148. // NewTimer is the Fake version of time.NewTimer(d).
  149. func (f *FakeClock) NewTimer(d time.Duration) Timer {
  150. f.lock.Lock()
  151. defer f.lock.Unlock()
  152. stopTime := f.time.Add(d)
  153. ch := make(chan time.Time, 1) // Don't block!
  154. timer := &fakeTimer{
  155. fakeClock: f,
  156. waiter: fakeClockWaiter{
  157. targetTime: stopTime,
  158. destChan: ch,
  159. },
  160. }
  161. f.waiters = append(f.waiters, timer.waiter)
  162. return timer
  163. }
  164. // NewTicker returns a new Ticker.
  165. func (f *FakeClock) NewTicker(d time.Duration) Ticker {
  166. f.lock.Lock()
  167. defer f.lock.Unlock()
  168. tickTime := f.time.Add(d)
  169. ch := make(chan time.Time, 1) // hold one tick
  170. f.waiters = append(f.waiters, fakeClockWaiter{
  171. targetTime: tickTime,
  172. stepInterval: d,
  173. skipIfBlocked: true,
  174. destChan: ch,
  175. })
  176. return &fakeTicker{
  177. c: ch,
  178. }
  179. }
  180. // Step moves clock by Duration, notifies anyone that's called After, Tick, or NewTimer
  181. func (f *FakeClock) Step(d time.Duration) {
  182. f.lock.Lock()
  183. defer f.lock.Unlock()
  184. f.setTimeLocked(f.time.Add(d))
  185. }
  186. // SetTime sets the time on a FakeClock.
  187. func (f *FakeClock) SetTime(t time.Time) {
  188. f.lock.Lock()
  189. defer f.lock.Unlock()
  190. f.setTimeLocked(t)
  191. }
  192. // Actually changes the time and checks any waiters. f must be write-locked.
  193. func (f *FakeClock) setTimeLocked(t time.Time) {
  194. f.time = t
  195. newWaiters := make([]fakeClockWaiter, 0, len(f.waiters))
  196. for i := range f.waiters {
  197. w := &f.waiters[i]
  198. if !w.targetTime.After(t) {
  199. if w.skipIfBlocked {
  200. select {
  201. case w.destChan <- t:
  202. default:
  203. }
  204. } else {
  205. w.destChan <- t
  206. }
  207. if w.afterFunc != nil {
  208. w.afterFunc()
  209. }
  210. if w.stepInterval > 0 {
  211. for !w.targetTime.After(t) {
  212. w.targetTime = w.targetTime.Add(w.stepInterval)
  213. }
  214. newWaiters = append(newWaiters, *w)
  215. }
  216. } else {
  217. newWaiters = append(newWaiters, f.waiters[i])
  218. }
  219. }
  220. f.waiters = newWaiters
  221. }
  222. // HasWaiters returns true if After or AfterFunc has been called on f but not yet satisfied
  223. // (so you can write race-free tests).
  224. func (f *FakeClock) HasWaiters() bool {
  225. f.lock.RLock()
  226. defer f.lock.RUnlock()
  227. return len(f.waiters) > 0
  228. }
  229. // Sleep pauses the FakeClock for duration d.
  230. func (f *FakeClock) Sleep(d time.Duration) {
  231. f.Step(d)
  232. }
  233. // IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration
  234. type IntervalClock struct {
  235. Time time.Time
  236. Duration time.Duration
  237. }
  238. // Now returns i's time.
  239. func (i *IntervalClock) Now() time.Time {
  240. i.Time = i.Time.Add(i.Duration)
  241. return i.Time
  242. }
  243. // Since returns time since the time in i.
  244. func (i *IntervalClock) Since(ts time.Time) time.Duration {
  245. return i.Time.Sub(ts)
  246. }
  247. // After is currently unimplemented, will panic.
  248. // TODO: make interval clock use FakeClock so this can be implemented.
  249. func (*IntervalClock) After(d time.Duration) <-chan time.Time {
  250. panic("IntervalClock doesn't implement After")
  251. }
  252. // AfterFunc is currently unimplemented, will panic.
  253. // TODO: make interval clock use FakeClock so this can be implemented.
  254. func (*IntervalClock) AfterFunc(d time.Duration, cb func()) Timer {
  255. panic("IntervalClock doesn't implement AfterFunc")
  256. }
  257. // NewTimer is currently unimplemented, will panic.
  258. // TODO: make interval clock use FakeClock so this can be implemented.
  259. func (*IntervalClock) NewTimer(d time.Duration) Timer {
  260. panic("IntervalClock doesn't implement NewTimer")
  261. }
  262. // NewTicker is currently unimplemented, will panic.
  263. // TODO: make interval clock use FakeClock so this can be implemented.
  264. func (*IntervalClock) NewTicker(d time.Duration) Ticker {
  265. panic("IntervalClock doesn't implement NewTicker")
  266. }
  267. // Sleep is currently unimplemented; will panic.
  268. func (*IntervalClock) Sleep(d time.Duration) {
  269. panic("IntervalClock doesn't implement Sleep")
  270. }
  271. // Timer allows for injecting fake or real timers into code that
  272. // needs to do arbitrary things based on time.
  273. type Timer interface {
  274. C() <-chan time.Time
  275. Stop() bool
  276. Reset(d time.Duration) bool
  277. }
  278. // realTimer is backed by an actual time.Timer.
  279. type realTimer struct {
  280. timer *time.Timer
  281. }
  282. // C returns the underlying timer's channel.
  283. func (r *realTimer) C() <-chan time.Time {
  284. return r.timer.C
  285. }
  286. // Stop calls Stop() on the underlying timer.
  287. func (r *realTimer) Stop() bool {
  288. return r.timer.Stop()
  289. }
  290. // Reset calls Reset() on the underlying timer.
  291. func (r *realTimer) Reset(d time.Duration) bool {
  292. return r.timer.Reset(d)
  293. }
  294. // fakeTimer implements Timer based on a FakeClock.
  295. type fakeTimer struct {
  296. fakeClock *FakeClock
  297. waiter fakeClockWaiter
  298. }
  299. // C returns the channel that notifies when this timer has fired.
  300. func (f *fakeTimer) C() <-chan time.Time {
  301. return f.waiter.destChan
  302. }
  303. // Stop conditionally stops the timer. If the timer has neither fired
  304. // nor been stopped then this call stops the timer and returns true,
  305. // otherwise this call returns false. This is like time.Timer::Stop.
  306. func (f *fakeTimer) Stop() bool {
  307. f.fakeClock.lock.Lock()
  308. defer f.fakeClock.lock.Unlock()
  309. // The timer has already fired or been stopped, unless it is found
  310. // among the clock's waiters.
  311. stopped := false
  312. oldWaiters := f.fakeClock.waiters
  313. newWaiters := make([]fakeClockWaiter, 0, len(oldWaiters))
  314. seekChan := f.waiter.destChan
  315. for i := range oldWaiters {
  316. // Identify the timer's fakeClockWaiter by the identity of the
  317. // destination channel, nothing else is necessarily unique and
  318. // constant since the timer's creation.
  319. if oldWaiters[i].destChan == seekChan {
  320. stopped = true
  321. } else {
  322. newWaiters = append(newWaiters, oldWaiters[i])
  323. }
  324. }
  325. f.fakeClock.waiters = newWaiters
  326. return stopped
  327. }
  328. // Reset conditionally updates the firing time of the timer. If the
  329. // timer has neither fired nor been stopped then this call resets the
  330. // timer to the fake clock's "now" + d and returns true, otherwise
  331. // it creates a new waiter, adds it to the clock, and returns true.
  332. //
  333. // It is not possible to return false, because a fake timer can be reset
  334. // from any state (waiting to fire, already fired, and stopped).
  335. //
  336. // See the GoDoc for time.Timer::Reset for more context on why
  337. // the return value of Reset() is not useful.
  338. func (f *fakeTimer) Reset(d time.Duration) bool {
  339. f.fakeClock.lock.Lock()
  340. defer f.fakeClock.lock.Unlock()
  341. waiters := f.fakeClock.waiters
  342. seekChan := f.waiter.destChan
  343. for i := range waiters {
  344. if waiters[i].destChan == seekChan {
  345. waiters[i].targetTime = f.fakeClock.time.Add(d)
  346. return true
  347. }
  348. }
  349. // No existing waiter, timer has already fired or been reset.
  350. // We should still enable Reset() to succeed by creating a
  351. // new waiter and adding it to the clock's waiters.
  352. newWaiter := fakeClockWaiter{
  353. targetTime: f.fakeClock.time.Add(d),
  354. destChan: seekChan,
  355. }
  356. f.fakeClock.waiters = append(f.fakeClock.waiters, newWaiter)
  357. return true
  358. }
  359. // Ticker defines the Ticker interface
  360. type Ticker interface {
  361. C() <-chan time.Time
  362. Stop()
  363. }
  364. type realTicker struct {
  365. ticker *time.Ticker
  366. }
  367. func (t *realTicker) C() <-chan time.Time {
  368. return t.ticker.C
  369. }
  370. func (t *realTicker) Stop() {
  371. t.ticker.Stop()
  372. }
  373. type fakeTicker struct {
  374. c <-chan time.Time
  375. }
  376. func (t *fakeTicker) C() <-chan time.Time {
  377. return t.c
  378. }
  379. func (t *fakeTicker) Stop() {
  380. }