| 71 self.daemon = True |
71 self.daemon = True |
| 72 self._list = None |
72 self._list = None |
| 73 |
73 |
| 74 def _insert(self, ev): |
74 def _insert(self, ev): |
| 75 if not self._list: |
75 if not self._list: |
| |
76 #logger.debug("Insert first") |
| 76 self._list=ev |
77 self._list=ev |
| 77 elif ev<self._list: |
78 elif ev<self._list: |
| |
79 #logger.debug("Insert beginning") |
| 78 self._list.insert_immediately_before(ev) |
80 self._list.insert_immediately_before(ev) |
| 79 self._list=ev |
81 self._list=ev |
| 80 else: |
82 else: |
| |
83 #logger.debug("Insert after") |
| 81 self._list.insert_after(ev) |
84 self._list.insert_after(ev) |
| 82 |
85 |
| 83 self._cond.notify() |
86 self._cond.notify() |
| 84 |
87 |
| 85 def _unlink(self, ev): |
88 def _unlink(self, ev): |
| 96 self.precision = precision |
99 self.precision = precision |
| 97 self._next_event_time = None |
100 self._next_event_time = None |
| 98 super().__init__(target = self._scheduler_thread, name = 'Scheduler') |
101 super().__init__(target = self._scheduler_thread, name = 'Scheduler') |
| 99 |
102 |
| 100 def _scheduler_thread(self): |
103 def _scheduler_thread(self): |
| |
104 logger.debug("Scheduler thread started") |
| 101 with self._cond: |
105 with self._cond: |
| 102 while not self._terminate: |
106 while not self._terminate: |
| 103 now = time.monotonic() |
107 now = time.monotonic() |
| 104 if not self._list: |
108 if not self._list: |
| 105 timeout = None |
109 timeout = None |
| 107 # Wait at most precision seconds, or until next event if it |
111 # Wait at most precision seconds, or until next event if it |
| 108 # comes earlier |
112 # comes earlier |
| 109 timeout=min(self.precision, self._list.when-now) |
113 timeout=min(self.precision, self._list.when-now) |
| 110 |
114 |
| 111 if not timeout or timeout>0: |
115 if not timeout or timeout>0: |
| |
116 logger.debug("Scheduler waiting %d seconds" % (timeout or (-1))) |
| 112 self._cond.wait(timeout) |
117 self._cond.wait(timeout) |
| 113 now = time.monotonic() |
118 now = time.monotonic() |
| |
119 |
| |
120 logger.debug("Scheduler timed out") |
| 114 |
121 |
| 115 while self._list and self._list.when <= now: |
122 while self._list and self._list.when <= now: |
| 116 ev=self._list |
123 ev=self._list |
| 117 logger.debug("Scheduler activating %s" % (ev.name or "(unknown)")) |
124 logger.debug("Scheduler activating %s" % (ev.name or "(unknown)")) |
| 118 # We are only allowed to remove ev from list when ev.cond allows |
125 # We are only allowed to remove ev from list when ev.cond allows |
| 134 with self._cond: |
141 with self._cond: |
| 135 self._unlink(ev) |
142 self._unlink(ev) |
| 136 |
143 |
| 137 # cond has to be acquired on entry! |
144 # cond has to be acquired on entry! |
| 138 def wait_until(self, when, cond, name=None): |
145 def wait_until(self, when, cond, name=None): |
| |
146 logger.debug("Scheduling '%s' at %d" % (name, when)) |
| 139 self._wait(ScheduledEvent(when, cond, name)) |
147 self._wait(ScheduledEvent(when, cond, name)) |
| 140 |
148 |