github.com/aclisp/heapster@v0.19.2-0.20160613100040-51756f899a96/Godeps/_workspace/src/k8s.io/kubernetes/pkg/util/clock.go (about) 1 /* 2 Copyright 2014 The Kubernetes Authors All rights reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package util 18 19 import ( 20 "sync" 21 "time" 22 ) 23 24 // Clock allows for injecting fake or real clocks into code that 25 // needs to do arbitrary things based on time. 26 type Clock interface { 27 Now() time.Time 28 Since(time.Time) time.Duration 29 After(d time.Duration) <-chan time.Time 30 Sleep(d time.Duration) 31 Tick(d time.Duration) <-chan time.Time 32 } 33 34 var ( 35 _ = Clock(RealClock{}) 36 _ = Clock(&FakeClock{}) 37 _ = Clock(&IntervalClock{}) 38 ) 39 40 // RealClock really calls time.Now() 41 type RealClock struct{} 42 43 // Now returns the current time. 44 func (RealClock) Now() time.Time { 45 return time.Now() 46 } 47 48 // Since returns time since the specified timestamp. 49 func (RealClock) Since(ts time.Time) time.Duration { 50 return time.Since(ts) 51 } 52 53 // Same as time.After(d). 54 func (RealClock) After(d time.Duration) <-chan time.Time { 55 return time.After(d) 56 } 57 58 func (RealClock) Tick(d time.Duration) <-chan time.Time { 59 return time.Tick(d) 60 } 61 62 func (RealClock) Sleep(d time.Duration) { 63 time.Sleep(d) 64 } 65 66 // FakeClock implements Clock, but returns an arbitrary time. 67 type FakeClock struct { 68 lock sync.RWMutex 69 time time.Time 70 71 // waiters are waiting for the fake time to pass their specified time 72 waiters []fakeClockWaiter 73 } 74 75 type fakeClockWaiter struct { 76 targetTime time.Time 77 stepInterval time.Duration 78 skipIfBlocked bool 79 destChan chan<- time.Time 80 } 81 82 func NewFakeClock(t time.Time) *FakeClock { 83 return &FakeClock{ 84 time: t, 85 } 86 } 87 88 // Now returns f's time. 89 func (f *FakeClock) Now() time.Time { 90 f.lock.RLock() 91 defer f.lock.RUnlock() 92 return f.time 93 } 94 95 // Since returns time since the time in f. 96 func (f *FakeClock) Since(ts time.Time) time.Duration { 97 f.lock.RLock() 98 defer f.lock.RUnlock() 99 return f.time.Sub(ts) 100 } 101 102 // Fake version of time.After(d). 103 func (f *FakeClock) After(d time.Duration) <-chan time.Time { 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 f.waiters = append(f.waiters, fakeClockWaiter{ 109 targetTime: stopTime, 110 destChan: ch, 111 }) 112 return ch 113 } 114 115 func (f *FakeClock) Tick(d time.Duration) <-chan time.Time { 116 f.lock.Lock() 117 defer f.lock.Unlock() 118 tickTime := f.time.Add(d) 119 ch := make(chan time.Time, 1) // hold one tick 120 f.waiters = append(f.waiters, fakeClockWaiter{ 121 targetTime: tickTime, 122 stepInterval: d, 123 skipIfBlocked: true, 124 destChan: ch, 125 }) 126 127 return ch 128 } 129 130 // Move clock by Duration, notify anyone that's called After or Tick 131 func (f *FakeClock) Step(d time.Duration) { 132 f.lock.Lock() 133 defer f.lock.Unlock() 134 f.setTimeLocked(f.time.Add(d)) 135 } 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 144 // Actually changes the time and checks any waiters. f must be write-locked. 145 func (f *FakeClock) setTimeLocked(t time.Time) { 146 f.time = t 147 newWaiters := make([]fakeClockWaiter, 0, len(f.waiters)) 148 for i := range f.waiters { 149 w := &f.waiters[i] 150 if !w.targetTime.After(t) { 151 152 if w.skipIfBlocked { 153 select { 154 case w.destChan <- t: 155 default: 156 } 157 } else { 158 w.destChan <- t 159 } 160 161 if w.stepInterval > 0 { 162 for !w.targetTime.After(t) { 163 w.targetTime = w.targetTime.Add(w.stepInterval) 164 } 165 newWaiters = append(newWaiters, *w) 166 } 167 168 } else { 169 newWaiters = append(newWaiters, f.waiters[i]) 170 } 171 } 172 f.waiters = newWaiters 173 } 174 175 // Returns true if After has been called on f but not yet satisfied (so you can 176 // write race-free tests). 177 func (f *FakeClock) HasWaiters() bool { 178 f.lock.RLock() 179 defer f.lock.RUnlock() 180 return len(f.waiters) > 0 181 } 182 183 func (f *FakeClock) Sleep(d time.Duration) { 184 f.Step(d) 185 } 186 187 // IntervalClock implements Clock, but each invocation of Now steps the clock forward the specified duration 188 type IntervalClock struct { 189 Time time.Time 190 Duration time.Duration 191 } 192 193 // Now returns i's time. 194 func (i *IntervalClock) Now() time.Time { 195 i.Time = i.Time.Add(i.Duration) 196 return i.Time 197 } 198 199 // Since returns time since the time in i. 200 func (i *IntervalClock) Since(ts time.Time) time.Duration { 201 return i.Time.Sub(ts) 202 } 203 204 // Unimplemented, will panic. 205 // TODO: make interval clock use FakeClock so this can be implemented. 206 func (*IntervalClock) After(d time.Duration) <-chan time.Time { 207 panic("IntervalClock doesn't implement After") 208 } 209 210 // Unimplemented, will panic. 211 // TODO: make interval clock use FakeClock so this can be implemented. 212 func (*IntervalClock) Tick(d time.Duration) <-chan time.Time { 213 panic("IntervalClock doesn't implement Tick") 214 } 215 216 func (*IntervalClock) Sleep(d time.Duration) { 217 panic("IntervalClock doesn't implement Sleep") 218 }