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  }