
Nick Coghlan wrote:
Completely unintuitive and unnecessary. With the GIL taking care of synchronisation issues, we can easily coerce time.time() into being a monotonic clock by the simple expedient of saving the last returned value: [snip]
Here's a version that doesn't suffer from the flaw of returning a long stream of constant values when the system clock jumps backwards a significant amount: class MockTime: def __init__(self): self.ticks = [1, 2, 3, 4, 2, 3, 4, 5, 7, 3, 4, 6, 7, 8, 8, 9] self.i = -1 def __call__(self): self.i += 1 return self.ticks[self.i] time = MockTime() _prev = _prev_raw = 0 def monotonic(): global _prev, _prev_raw raw = time() delta = max(0, raw - _prev_raw) _prev_raw = raw _prev += delta return _prev And in use:
[monotonic() for i in range(16)] [1, 2, 3, 4, 4, 5, 6, 7, 9, 9, 10, 12, 13, 14, 14, 15]
Time: [1, 2, 3, 4, 2, 3, 4, 5, 7, 3, 4, 6, 7, 8, 8, 9] Nick: [1, 2, 3, 4, 4, 4, 4, 5, 7, 7, 7, 7, 7, 8, 8, 9] Mine: [1, 2, 3, 4, 4, 5, 6, 7, 9, 9, 10, 12, 13, 14, 14, 15] Mine will get ahead of the system clock each time it jumps back, but it's a lot closer to the ideal of a *strictly* monotonically increasing clock. Assuming that the system clock will never jump backwards twice in a row, the double-caching version will never have more than two constant values in a row. -- Steven