monotonic.go 1019 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. package missinggo
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. // Monotonic time represents time since an arbitrary point in the past, where
  7. // the concept of now is only ever moving in a positive direction.
  8. type MonotonicTime struct {
  9. skewedStdTime time.Time
  10. }
  11. func (me MonotonicTime) Sub(other MonotonicTime) time.Duration {
  12. return me.skewedStdTime.Sub(other.skewedStdTime)
  13. }
  14. var (
  15. stdNowFunc = time.Now
  16. monotonicMu sync.Mutex
  17. lastStdNow time.Time
  18. monotonicSkew time.Duration
  19. )
  20. func skewedStdNow() time.Time {
  21. monotonicMu.Lock()
  22. defer monotonicMu.Unlock()
  23. stdNow := stdNowFunc()
  24. if !lastStdNow.IsZero() && stdNow.Before(lastStdNow) {
  25. monotonicSkew += lastStdNow.Sub(stdNow)
  26. }
  27. lastStdNow = stdNow
  28. return stdNow.Add(monotonicSkew)
  29. }
  30. // Consecutive calls always produce the same or greater time than previous
  31. // calls.
  32. func MonotonicNow() MonotonicTime {
  33. return MonotonicTime{skewedStdNow()}
  34. }
  35. func MonotonicSince(since MonotonicTime) (ret time.Duration) {
  36. return skewedStdNow().Sub(since.skewedStdTime)
  37. }