Source code for rhythm.libclock
"""
System clock management and query interface.
"""
import contextlib
import functools
from . import abstract
from . import system as clockwork
[docs]class Clock(object):
"""
Operating System's :py:class:`rhythm.abstract.Clock` implementation.
"""
__slots__ = ('unit', 'lib', 'clockwork', '_monotonic', '_sleeper')
def __init__(self, unit, lib, clockwork = clockwork):
self.unit = unit
self.lib = lib
self.clockwork = clockwork
# Used as the process' monotonic clock.
# Forks *must* inherit the state.
self._monotonic = self.clockwork.Chronometer()
class Sleeper(clockwork.Sleeper):
__slots__ = ()
def __next__(self, Measure = lib.Measure):
return Measure(super().__next__())
self._sleeper = Sleeper
def sleep(self, x):
return self.lib.Measure(self.clockwork.sleep_ns(x))
def sleeper(self):
return self._sleeper()
def delta(self, _map=map):
return _map(self.lib.Measure, self.clockwork.Chronometer())
def meter(self, *args, **kw):
m = self.lib.Measure
delay = m.of(*args, **kw)
meter = self.clockwork.Chronometer()
del args
del kw
# yield zero and init the chronometer's previous value
yield m(next(meter))
# from here, we just grab snapshots and let the device do the math
get = meter.snapshot
del meter
if delay:
while True:
yield m(get())
self.sleep(delay)
else:
del delay
while True:
yield m(get())
def periods(self, period):
current = 0
for x in self.delta():
current += x
if current > period:
count, current = divmod(current, period)
yield (count, period - current)
else:
yield (0, period - current)
@contextlib.contextmanager
def stopwatch(self, _partial = functools.partial):
meter = self.meter().__next__
cell = []
def inspect(meter=meter,cell=cell):
if cell:
return cell[0]
else:
return meter()
try:
meter() # start it
yield inspect
finally:
cell.append(meter())
def monotonic(self):
return self.lib.Measure(self._monotonic.snapshot())
def demotic(self):
return self.lib.Timestamp(self.clockwork.snapshot_ns())
abstract.Clock.register(Clock)