123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 |
- from dataclasses import dataclass
- from numbers import Real # superclass for 'int' and 'float'
- from sccd.util.duration import *
- # The only requirement for a TimeImplementation is that the diffs between get_time call results are real durations of a non-complex number type (int, float).
- @dataclass
- class TimeImplementation:
- time_unit: Duration
- get_time: Callable[[], Real]
- # This is the most accurate time function in Python 3.6
- from time import perf_counter
- PerfCounterTime = TimeImplementation(
- time_unit=duration(1, Second),
- get_time=perf_counter) # returns float
- DefaultTimeImplementation = PerfCounterTime
- # Python >= 3.7 has a better time function
- import sys
- if sys.version_info.minor >= 7:
- from time import perf_counter_ns
- PerfCounterNSTime = TimeImplementation(
- time_unit=duration(1, Nanosecond),
- get_time=perf_counter_ns) # returns int
- DefaultTimeImplementation = PerfCounterNSTime
- # A simple "chrono" timer, using a configurable time function to measure wall-clock time passed since its start,
- # returning elapsed times in a configurable fixed unit, efficiently.
- class Timer:
- def __init__(self, impl: TimeImplementation, unit: Duration):
- self.impl = impl
- self.unit = unit
- self.paused_at = 0
- self.started_at = None
- self.convert = lambda x: int(get_conversion_f(
- from_unit=self.impl.time_unit, to_unit=unit)(x))
- self.paused = True
- # Start (if not paused) or continue timer (if paused)
- def start(self):
- self.started_at = self.convert(self.impl.get_time()) + self.paused_at
- self.paused = False
- def pause(self):
- self.paused_at = self.now()
- self.paused = True
- # The number returned will be the wall-clock time elapsed since the call to start(),
- # divided by the 'unit' passed to the constructor of this object, minus of course
- # the time elapsed while the timer was 'paused'.
- def now(self) -> int:
- assert not self.paused
- return self.convert(self.impl.get_time()) - self.started_at
- def is_paused(self) -> bool:
- return self.paused
- # Note: We could add a reset() method, but we simply don't need it for our purposes :)
|