# HG changeset patch # User Tuomo Valkonen # Date 1517137305 0 # Node ID e8773133bf79be9a985518cc64fa9b75cb157129 # Parent 4b08fca3ce34c6af3855121c38e010972c3e8ff6 DreamTime.monotonic() no longer needs to call time.monotonic() so is more "static" within wakeup periods, and so comparable to time.monotonic() realisations. Also some PyObjC weirdness handling. diff -r 4b08fca3ce34 -r e8773133bf79 sleep.py --- a/sleep.py Sun Jan 28 00:11:18 2018 +0000 +++ b/sleep.py Sun Jan 28 11:01:45 2018 +0000 @@ -7,24 +7,29 @@ import platform import time import threading -import borgend import weakref import datetime +import borgend logger=borgend.logger.getChild(__name__) -_dreamtime_monitor=[None] +_dreamtime_monitor=None # # Support classes for dealing with different times # -def dreamtime(): - if _dreamtime_monitor[0]: - return max(0, time.monotonic()-_dreamtime_monitor[0].diff()) +# Return difference (delay) of "dreamtime" to monotonic time +def dreamtime_difference(): + if _dreamtime_monitor: + return _dreamtime_monitor.diff() else: return time.monotonic() +# Return "dreamtime" +def dreamtime(): + return max(0, time.monotonic()-dreamtime_difference()) + class Time: def realtime(self): raise NotImplementedError @@ -108,8 +113,11 @@ def realtime(self): return self._value+(time.time()-dreamtime()) + # Important: monotonic is "static" within a wakeup period + # and does not need to call time.monotonic(), as it gets compared + # to a specific time.monotonic() realisation def monotonic(self): - return self._value+(time.monotonic()-dreamtime()) + return self._value+dreamtime_difference() @staticmethod def _now(): @@ -126,28 +134,28 @@ self.__sleeptime=None self.__slept=0 self.__epoch=time.monotonic() - self._lock=threading.Lock() - self._callbacks=weakref.WeakKeyDictionary() + self.__lock=threading.Lock() + self.__callbacks=weakref.WeakKeyDictionary() return self def handleSleepNotification_(self, aNotification): logger.info("System going to sleep") now=time.monotonic() - with self._lock: + with self.__lock: self.__sleeptime=now def handleWakeNotification_(self, aNotification): logger.info("System waking up from sleep") try: now=time.monotonic() - with self._lock: + with self.__lock: if self.__sleeptime: slept=max(0, now-self.__sleeptime) logger.info("Slept %f seconds" % slept) self.__slept=self.__slept+slept self.__sleeptime=None - callbacks=self._callbacks.copy() + callbacks=self.__callbacks.copy() except: logger.exception("Bug in wakeup handler") @@ -159,40 +167,42 @@ # Return difference to time.monotonic() def diff(self): - with self._lock: + with self.__lock: diff=self.__epoch+self.__slept return diff - # Obj-C hates this - # def add_callback(self, obj, callback): - # with self.lock: - # self.__callbacks[obj]=callback + # Weirdo (Py)ObjC naming to stop it form choking up + def addForObj_aCallback_(self, obj, callback): + with self.__lock: + self.__callbacks[obj]=callback # obj is to use a a key in a weak key dictionary def add_callback(obj, callback): - monitor=_dreamtime_monitor[0] + global _dreamtime_monitor + + monitor=_dreamtime_monitor if not monitor: raise Exception("Dreamtime monitor not started") else: - #monitor.add_my_callback(obj, callback) - with monitor._lock: - monitor._callbacks[obj]=callback + monitor.addForObj_aCallback_(obj, callback) def start_monitoring(): + global _dreamtime_monitor + if platform.system()=='Darwin': logger.debug("Starting to monitor system sleep") workspace = AppKit.NSWorkspace.sharedWorkspace() notification_center = workspace.notificationCenter() - _dreamtime_monitor[0] = SleepHandler.new() + _dreamtime_monitor = SleepHandler.new() notification_center.addObserver_selector_name_object_( - _dreamtime_monitor[0], + _dreamtime_monitor, "handleSleepNotification:", AppKit.NSWorkspaceWillSleepNotification, None) notification_center.addObserver_selector_name_object_( - _dreamtime_monitor[0], + _dreamtime_monitor, "handleWakeNotification:", AppKit.NSWorkspaceDidWakeNotification, None)