--- a/scheduler.py Sat Jan 27 12:19:39 2018 +0000 +++ b/scheduler.py Sun Jan 28 00:11:18 2018 +0000 @@ -6,6 +6,7 @@ import time import borgend +import sleep from threading import Condition, Lock, Thread logger=borgend.logger.getChild(__name__) @@ -45,8 +46,11 @@ n.prev=p if p: p.next=n + self.next=None + self.prev=None class ScheduledEvent(QueuedEvent): + #@accepts(ScheduledEvent, sleep.Time, threading.Cond, str) def __init__(self, when, cond, name=None): super().__init__(cond, name=name) self.when=when @@ -90,6 +94,16 @@ self._list=ev.next ev.unlink() + def _resort(self): + oldlist=self._list + self._list=None + while oldlist: + ev=oldlist + oldlist=oldlist.next + ev.unlink() + self._insert(ev) + + class Scheduler(QueueThread): # Default to precision of 60 seconds: the scheduler thread will never @@ -99,6 +113,7 @@ self.precision = precision self._next_event_time = None super().__init__(target = self._scheduler_thread, name = 'Scheduler') + sleep.add_callback(self, self._wakeup_callback) def _scheduler_thread(self): logger.debug("Scheduler thread started") @@ -110,7 +125,7 @@ else: # Wait at most precision seconds, or until next event if it # comes earlier - timeout=min(self.precision, self._list.when-now) + timeout=min(self.precision, self._list.when.realtime()-now) if not timeout or timeout>0: logger.debug("Scheduler waiting %d seconds" % (timeout or (-1))) @@ -119,7 +134,7 @@ logger.debug("Scheduler timed out") - while self._list and self._list.when <= now: + while self._list and self._list.when.monotonic() <= now: ev=self._list logger.debug("Scheduler activating %s" % (ev.name or "(unknown)")) # We are only allowed to remove ev from list when ev.cond allows @@ -128,6 +143,11 @@ ev.unlink() ev.cond.notifyAll() + def _wakeup_callback(self): + logger.debug("Rescheduling events after wakeup") + with self._cond: + self._resort() + def _wait(self, ev): with self._cond: self._insert(ev) @@ -143,6 +163,7 @@ # cond has to be acquired on entry! def wait_until(self, when, cond, name=None): - logger.debug("Scheduling '%s' at %d" % (name, when)) + logger.debug("Scheduling '%s' in %s seconds [%s]" % + (name, when.seconds_to(), when.__class__.__name__)) self._wait(ScheduledEvent(when, cond, name))