timer.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  2. Copyright 2023 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 wait
  14. import (
  15. "time"
  16. "k8s.io/utils/clock"
  17. )
  18. // Timer abstracts how wait functions interact with time runtime efficiently. Test
  19. // code may implement this interface directly but package consumers are encouraged
  20. // to use the Backoff type as the primary mechanism for acquiring a Timer. The
  21. // interface is a simplification of clock.Timer to prevent misuse. Timers are not
  22. // expected to be safe for calls from multiple goroutines.
  23. type Timer interface {
  24. // C returns a channel that will receive a struct{} each time the timer fires.
  25. // The channel should not be waited on after Stop() is invoked. It is allowed
  26. // to cache the returned value of C() for the lifetime of the Timer.
  27. C() <-chan time.Time
  28. // Next is invoked by wait functions to signal timers that the next interval
  29. // should begin. You may only use Next() if you have drained the channel C().
  30. // You should not call Next() after Stop() is invoked.
  31. Next()
  32. // Stop releases the timer. It is safe to invoke if no other methods have been
  33. // called.
  34. Stop()
  35. }
  36. type noopTimer struct {
  37. closedCh <-chan time.Time
  38. }
  39. // newNoopTimer creates a timer with a unique channel to avoid contention
  40. // for the channel's lock across multiple unrelated timers.
  41. func newNoopTimer() noopTimer {
  42. ch := make(chan time.Time)
  43. close(ch)
  44. return noopTimer{closedCh: ch}
  45. }
  46. func (t noopTimer) C() <-chan time.Time {
  47. return t.closedCh
  48. }
  49. func (noopTimer) Next() {}
  50. func (noopTimer) Stop() {}
  51. type variableTimer struct {
  52. fn DelayFunc
  53. t clock.Timer
  54. new func(time.Duration) clock.Timer
  55. }
  56. func (t *variableTimer) C() <-chan time.Time {
  57. if t.t == nil {
  58. d := t.fn()
  59. t.t = t.new(d)
  60. }
  61. return t.t.C()
  62. }
  63. func (t *variableTimer) Next() {
  64. if t.t == nil {
  65. return
  66. }
  67. d := t.fn()
  68. t.t.Reset(d)
  69. }
  70. func (t *variableTimer) Stop() {
  71. if t.t == nil {
  72. return
  73. }
  74. t.t.Stop()
  75. t.t = nil
  76. }
  77. type fixedTimer struct {
  78. interval time.Duration
  79. t clock.Ticker
  80. new func(time.Duration) clock.Ticker
  81. }
  82. func (t *fixedTimer) C() <-chan time.Time {
  83. if t.t == nil {
  84. t.t = t.new(t.interval)
  85. }
  86. return t.t.C()
  87. }
  88. func (t *fixedTimer) Next() {
  89. // no-op for fixed timers
  90. }
  91. func (t *fixedTimer) Stop() {
  92. if t.t == nil {
  93. return
  94. }
  95. t.t.Stop()
  96. t.t = nil
  97. }
  98. var (
  99. // RealTimer can be passed to methods that need a clock.Timer.
  100. RealTimer = clock.RealClock{}.NewTimer
  101. )
  102. var (
  103. // internalClock is used for test injection of clocks
  104. internalClock = clock.RealClock{}
  105. )