diff options
Diffstat (limited to 'policyhandler/step_timer.py')
-rw-r--r-- | policyhandler/step_timer.py | 121 |
1 files changed, 68 insertions, 53 deletions
diff --git a/policyhandler/step_timer.py b/policyhandler/step_timer.py index ad77c85..3936107 100644 --- a/policyhandler/step_timer.py +++ b/policyhandler/step_timer.py @@ -19,7 +19,7 @@ """periodically callback""" from datetime import datetime -from threading import Event, Lock, Thread +from threading import Event, RLock, Thread class StepTimer(Thread): @@ -40,67 +40,75 @@ class StepTimer(Thread): self._args = args self._kwargs = kwargs - self._lock = Lock() + self._lock = RLock() self._timeout = Event() - self._paused = Event() + self._waiting_for_timeout = False self._next = Event() - self._finished = Event() + self._paused = False + self._finished = False - self._event = StepTimer.INIT - self._event_counter = 0 - self._event_time = 0 - self._event_ts = datetime.now() + self._request = StepTimer.INIT + self._req_count = 0 + self._req_time = 0 + self._req_ts = datetime.now() self._substep = None self._substep_time = 0 self._substep_ts = datetime.now() - def get_status(self): - """returns status of events""" + def get_timer_status(self): + """returns timer status""" with self._lock: return "{0}[{1}] {2}: timeout({3}), paused({4}), next({5}), finished({6})".format( - self._event, - self._event_counter, + self._request, + self._req_count, self._substep, self._timeout.is_set(), - self._paused.is_set(), + self._paused, self._next.is_set(), - self._finished.is_set(), + self._finished, ) def next(self): """continue with the next timeout""" - self._paused.clear() - self._next.set() - self._timeout.set() - self._set_timer_event(StepTimer.NEXT) + with self._lock: + self._paused = False + if self._waiting_for_timeout: + self._next.set() + self._timeout.set() + else: + self._next.set() + self._request_to_timer(StepTimer.NEXT) def pause(self): """pause the timer""" - self._paused.set() - self._next.clear() - self._set_timer_event(StepTimer.PAUSED) + with self._lock: + self._paused = True + self._next.clear() + self._request_to_timer(StepTimer.PAUSED) def stop(self): """stop the timer if it hasn't finished yet""" - self._finished.set() - self._timeout.set() - self._next.set() - self._set_timer_event(StepTimer.STOPPING) + with self._lock: + self._finished = True + self._timeout.set() + self._next.set() + self._request_to_timer(StepTimer.STOPPING) - def _set_timer_event(self, event): - """set the event on the timer""" + def _request_to_timer(self, request): + """set the request on the timer""" with self._lock: - if event in [StepTimer.NEXT, StepTimer.STARTED]: - self._event_counter += 1 + if request in [StepTimer.NEXT, StepTimer.STARTED]: + self._req_count += 1 - self._event = event + prev_req = self._request + self._request = request now = datetime.now() - self._event_time = (now - self._event_ts).total_seconds() - self._event_ts = now - self._logger.info("[{0}] {1} {2}".format( - self._event_time, self.name, self.get_status())) + self._req_time = (now - self._req_ts).total_seconds() + self._req_ts = now + self._logger.info("{0}[{1}] {2}->{3}".format( + self.name, self._req_time, prev_req, self.get_timer_status())) def _timer_substep(self, substep): """log exe step""" @@ -109,27 +117,34 @@ class StepTimer(Thread): now = datetime.now() self._substep_time = (now - self._substep_ts).total_seconds() self._substep_ts = now - self._logger.info("[{0}] {1}".format(self._substep_time, self.get_status())) + self._logger.info("[{0}] {1}".format(self._substep_time, self.get_timer_status())) def run(self): """loop one step a time until stopped=finished""" - self._set_timer_event(StepTimer.STARTED) + self._request_to_timer(StepTimer.STARTED) while True: - self._timer_substep("waiting for timeout {0}...".format(self._interval)) - self._timeout.wait(self._interval) - self._timer_substep("woke up after timeout") + with self._lock: + self._timeout.clear() + self._waiting_for_timeout = True + self._timer_substep("waiting for timeout {0}...".format(self._interval)) - if self._finished.is_set(): - self._timer_substep("finished") - break + interrupted = self._timeout.wait(self._interval) - if self._next.is_set(): - self._next.clear() - self._timeout.clear() - self._timer_substep("restart timer") - continue + with self._lock: + self._waiting_for_timeout = False + self._timer_substep("woke up after {0}timeout" + .format((interrupted and "interrupted ") or "")) + + if self._finished: + self._timer_substep("finished") + break - if self._paused.is_set(): + if self._next.is_set() and interrupted: + self._next.clear() + self._timer_substep("restart timer") + continue + + if self._paused: self._timer_substep("paused - skip on_time event") else: self._timer_substep("on_time event") @@ -137,12 +152,12 @@ class StepTimer(Thread): self._timer_substep("waiting for next...") self._next.wait() - self._next.clear() - self._timeout.clear() - self._timer_substep("woke up on next") + with self._lock: + self._next.clear() + self._timer_substep("woke up on next") - if self._finished.is_set(): + if self._finished: self._timer_substep("finished") break - self._set_timer_event(StepTimer.STOPPED) + self._request_to_timer(StepTimer.STOPPED) |