import time import threading import sys # TODO: Maybe Interval should be a multiply of Precision. class Job: Interval = 0 Elapsed = 0 JobFunction = None Force = False class JobController(threading.Thread): def __init__(self,precision=1.0): threading.Thread.__init__(self) self.__StopIt = False self.__Jobs = {} self.__JobCounter = 0 self.__Precision = precision self.__JobsLock = threading.Lock() def run(self): while(1): jobfuncs = [] if self.__StopIt == True: return self.__JobsLock.acquire() try: for key,val in self.__Jobs.items(): val.Elapsed += self.__Precision if val.Elapsed >= val.Interval or val.Force: val.Elapsed = 0 val.Force = False # copy to another list for # not acquirirng JobsLock() # while calling the JobsFunction jobfuncs.append(val.JobFunction) finally: self.__JobsLock.release() # now invoke the job functions for jobfunc in jobfuncs: try: jobfunc() # no unhandled exceptions allowed except Exception,e: print "JOBERROR:"+str(e) time.sleep(self.__Precision) def JcStart(self): self.start() def JcStop(self): self.__StopIt = True def __AssertBounds(self,val,min,max): if (val < min) or (val > max): raise AssertionError, "value not in bounds" \ "["+str(val)+"]["+str(min)+"]["+str(max)+"]" def JcAddJob(self,interval,jobfunction): self.__AssertBounds(interval,self.__Precision,float(sys.maxint)) # create a job object ajob = Job() ajob.Interval = interval ajob.Elapsed = 0 ajob.JobFunction = jobfunction ajob.Force = False # append it to jobs dict self.__JobCounter += 1 self.__JobsLock.acquire() try: self.__Jobs[self.__JobCounter] = ajob finally: self.__JobsLock.release() return self.__JobCounter def JcRemoveJob(self,jobid): self.__JobsLock.acquire() try: del self.__Jobs[jobid] finally: self.__JobsLock.release() def JcForceJob(self,jobid): self.__JobsLock.acquire() try: self.__Jobs[jobid].Force = True finally: self.__JobsLock.release() def JcChangeJob(self,jobid,interval,jobfunction): self.__AssertBounds(interval,self.__Precision,sys.maxint) self.__JobsLock.acquire() try: self.__Jobs[jobid].Interval = interval self.__Jobs[jobid].JobFunction = jobfunction finally: self.__JobsLock.release() # EXAMPLE A simple example is like this: jc = JobController(60.0) # precision is 60 secs, so main JobController will be invoked # per 60 secs. jc.JcAddJob(60*30,CheckConnectionJob) jc.JcAddJob(60*5,CheckStatisticsJob) jc.start() jc.JcAddJob(60*5,CheckPingJob) . .