sleep.py

changeset 77
e8773133bf79
parent 76
4b08fca3ce34
equal deleted inserted replaced
76:4b08fca3ce34 77:e8773133bf79
5 import Foundation 5 import Foundation
6 import AppKit 6 import AppKit
7 import platform 7 import platform
8 import time 8 import time
9 import threading 9 import threading
10 import borgend
11 import weakref 10 import weakref
12 import datetime 11 import datetime
12 import borgend
13 13
14 logger=borgend.logger.getChild(__name__) 14 logger=borgend.logger.getChild(__name__)
15 15
16 _dreamtime_monitor=[None] 16 _dreamtime_monitor=None
17 17
18 # 18 #
19 # Support classes for dealing with different times 19 # Support classes for dealing with different times
20 # 20 #
21 21
22 def dreamtime(): 22 # Return difference (delay) of "dreamtime" to monotonic time
23 if _dreamtime_monitor[0]: 23 def dreamtime_difference():
24 return max(0, time.monotonic()-_dreamtime_monitor[0].diff()) 24 if _dreamtime_monitor:
25 return _dreamtime_monitor.diff()
25 else: 26 else:
26 return time.monotonic() 27 return time.monotonic()
28
29 # Return "dreamtime"
30 def dreamtime():
31 return max(0, time.monotonic()-dreamtime_difference())
27 32
28 class Time: 33 class Time:
29 def realtime(self): 34 def realtime(self):
30 raise NotImplementedError 35 raise NotImplementedError
31 36
106 self._value=when 111 self._value=when
107 112
108 def realtime(self): 113 def realtime(self):
109 return self._value+(time.time()-dreamtime()) 114 return self._value+(time.time()-dreamtime())
110 115
111 def monotonic(self): 116 # Important: monotonic is "static" within a wakeup period
112 return self._value+(time.monotonic()-dreamtime()) 117 # and does not need to call time.monotonic(), as it gets compared
118 # to a specific time.monotonic() realisation
119 def monotonic(self):
120 return self._value+dreamtime_difference()
113 121
114 @staticmethod 122 @staticmethod
115 def _now(): 123 def _now():
116 return dreamtime() 124 return dreamtime()
117 125
124 132
125 def init(self): 133 def init(self):
126 self.__sleeptime=None 134 self.__sleeptime=None
127 self.__slept=0 135 self.__slept=0
128 self.__epoch=time.monotonic() 136 self.__epoch=time.monotonic()
129 self._lock=threading.Lock() 137 self.__lock=threading.Lock()
130 self._callbacks=weakref.WeakKeyDictionary() 138 self.__callbacks=weakref.WeakKeyDictionary()
131 139
132 return self 140 return self
133 141
134 def handleSleepNotification_(self, aNotification): 142 def handleSleepNotification_(self, aNotification):
135 logger.info("System going to sleep") 143 logger.info("System going to sleep")
136 now=time.monotonic() 144 now=time.monotonic()
137 with self._lock: 145 with self.__lock:
138 self.__sleeptime=now 146 self.__sleeptime=now
139 147
140 def handleWakeNotification_(self, aNotification): 148 def handleWakeNotification_(self, aNotification):
141 logger.info("System waking up from sleep") 149 logger.info("System waking up from sleep")
142 try: 150 try:
143 now=time.monotonic() 151 now=time.monotonic()
144 with self._lock: 152 with self.__lock:
145 if self.__sleeptime: 153 if self.__sleeptime:
146 slept=max(0, now-self.__sleeptime) 154 slept=max(0, now-self.__sleeptime)
147 logger.info("Slept %f seconds" % slept) 155 logger.info("Slept %f seconds" % slept)
148 self.__slept=self.__slept+slept 156 self.__slept=self.__slept+slept
149 self.__sleeptime=None 157 self.__sleeptime=None
150 callbacks=self._callbacks.copy() 158 callbacks=self.__callbacks.copy()
151 except: 159 except:
152 logger.exception("Bug in wakeup handler") 160 logger.exception("Bug in wakeup handler")
153 161
154 for callback in callbacks.values(): 162 for callback in callbacks.values():
155 try: 163 try:
157 except Exception: 165 except Exception:
158 logger.exception("Error in wake notification callback") 166 logger.exception("Error in wake notification callback")
159 167
160 # Return difference to time.monotonic() 168 # Return difference to time.monotonic()
161 def diff(self): 169 def diff(self):
162 with self._lock: 170 with self.__lock:
163 diff=self.__epoch+self.__slept 171 diff=self.__epoch+self.__slept
164 return diff 172 return diff
165 173
166 # Obj-C hates this 174 # Weirdo (Py)ObjC naming to stop it form choking up
167 # def add_callback(self, obj, callback): 175 def addForObj_aCallback_(self, obj, callback):
168 # with self.lock: 176 with self.__lock:
169 # self.__callbacks[obj]=callback 177 self.__callbacks[obj]=callback
170 178
171 # obj is to use a a key in a weak key dictionary 179 # obj is to use a a key in a weak key dictionary
172 def add_callback(obj, callback): 180 def add_callback(obj, callback):
173 monitor=_dreamtime_monitor[0] 181 global _dreamtime_monitor
182
183 monitor=_dreamtime_monitor
174 if not monitor: 184 if not monitor:
175 raise Exception("Dreamtime monitor not started") 185 raise Exception("Dreamtime monitor not started")
176 else: 186 else:
177 #monitor.add_my_callback(obj, callback) 187 monitor.addForObj_aCallback_(obj, callback)
178 with monitor._lock:
179 monitor._callbacks[obj]=callback
180 188
181 def start_monitoring(): 189 def start_monitoring():
190 global _dreamtime_monitor
191
182 if platform.system()=='Darwin': 192 if platform.system()=='Darwin':
183 logger.debug("Starting to monitor system sleep") 193 logger.debug("Starting to monitor system sleep")
184 workspace = AppKit.NSWorkspace.sharedWorkspace() 194 workspace = AppKit.NSWorkspace.sharedWorkspace()
185 notification_center = workspace.notificationCenter() 195 notification_center = workspace.notificationCenter()
186 _dreamtime_monitor[0] = SleepHandler.new() 196 _dreamtime_monitor = SleepHandler.new()
187 197
188 notification_center.addObserver_selector_name_object_( 198 notification_center.addObserver_selector_name_object_(
189 _dreamtime_monitor[0], 199 _dreamtime_monitor,
190 "handleSleepNotification:", 200 "handleSleepNotification:",
191 AppKit.NSWorkspaceWillSleepNotification, 201 AppKit.NSWorkspaceWillSleepNotification,
192 None) 202 None)
193 203
194 notification_center.addObserver_selector_name_object_( 204 notification_center.addObserver_selector_name_object_(
195 _dreamtime_monitor[0], 205 _dreamtime_monitor,
196 "handleWakeNotification:", 206 "handleWakeNotification:",
197 AppKit.NSWorkspaceDidWakeNotification, 207 AppKit.NSWorkspaceDidWakeNotification,
198 None) 208 None)
199 else: 209 else:
200 logger.warning(("No system sleep monitor implemented for '%s'" 210 logger.warning(("No system sleep monitor implemented for '%s'"

mercurial