from time import time from threading import Thread try: # for Python < 2.3 True, False except NameError: True, False = 1, 0 class TaskHandler: """The task handler. While the Task class only knows what task to perform with the run()-method, the TaskHandler has all the knowledge about the periodicity of the task. Instances of this class are managed by the Scheduler in the scheduled, running and onDemand dictionaries. """ ## Init ## def __init__(self, scheduler, start, period, task, name): self._scheduler = scheduler self._task = task self._name = name self._thread = None self._isRunning = False self._suspend = False self._lastTime = None self._startTime = start self._registerTime = time() self._reregister = True self._rerun = False self._period = abs(period) ## Scheduling ## def reset(self, start, period, task, reregister): self._startTime = start self._period = abs(period) self._task = task self._reregister = reregister def runTask(self): """Run this task in a background thread.""" if self._suspend: self._scheduler.notifyCompletion(self) return self._rerun = False self._thread = Thread(None, self._task._run, self.name(), (self,)) self._isRunning = True self._thread.start() def reschedule(self): """Determine whether this task should be rescheduled. Increments the startTime and returns true if this is a periodically executed task. """ if self._period == 0 or not self._reregister: return False else: if self._lastTime - self._startTime > self._period: # if the time taken to run the task exceeds the period self._startTime = self._lastTime + self._period else: self._startTime += self._period return True def notifyCompletion(self): self._isRunning = False self._lastTime = time() self._scheduler.notifyCompletion(self) def notifyFailure(self): self._isRunning = False self._lastTime = time() self._scheduler.notifyFailure(self) ## Attributes ## def isRunning(self): return self._isRunning def runAgain(self): """Determine whether this task should be run again. This method lets the Scheduler check to see whether this task should be re-run when it terminates. """ return self._rerun def isOnDemand(self): """Return True if this task is not scheduled for periodic execution.""" return self._period == 0 def runOnCompletion(self): """Request that this task be re-run after its current completion. Intended for on-demand tasks that are requested by the Scheduler while they are already running. """ self._rerun = True def unregister(self): """Request that this task not be kept after its current completion. Used to remove a task from the scheduler. """ self._reregister = False self._rerun = False def disable(self): """Disable future invocations of this task.""" self._suspend = True def enable(self): """Enable future invocations of this task.""" self._suspend = False def period(self): """Return the period of this task.""" return self._period def setPeriod(self, period): """Change the period for this task.""" self._period = period def stop(self): self._isRunning = False def name(self): return self._name def startTime(self, newTime=None): if newTime: self._startTime = newTime return self._startTime