aboutsummaryrefslogtreecommitdiffstats
path: root/policyhandler/step_timer.py
diff options
context:
space:
mode:
Diffstat (limited to 'policyhandler/step_timer.py')
-rw-r--r--policyhandler/step_timer.py121
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)