Single thread implementation of multiple timers
newtimer.py
Copy the Code code as follows:
#!/usr/bin/env python
From HEAPQ Import *
From threading Import Timer
Import threading
Import UUID
Import time
Import datetime
Import Sys
Import Math
Global Timerstamp
Global Timertimes
Class Cancelfail (Exception):
Pass
Class Slot (object):
def __init__ (self, period=0, interval=1, Function=none, args=[], kwargs={}):
Self.period = Period
self.pc = 0
Self.interval = Interval
Self.fire = 0
Self.id = UUID.UUID1 ()
Self.function = function
Self.args = args
Self.kwargs = Kwargs
#system resolution Millisecond
Class Newtimer (object):
#set enough time make thread sleep, when Newtimer empty set enoug time, too
#make sure sum of your timer call back function execute time shorter than resolution
#todo use a worker, thread to operate, Timer call back function
def __init__ (self, resolution=1000):
Global Timerstamp
timerstamp = Int (time.time () * 1000)
Self.nofire = Sys.maxint #next Fire time interval
Self.firestamp = Self.nofire + timerstamp
self.resolution = resolution# 1s
Self.lock = Threading. Rlock ()
self.wait = Dict ()
Self.ready = Dict ()
Self._start ()
"" "Private Operate Ready List" "
def _addtoreadylist (self, slot, Firestamp):
box = Dict ([(Slot.id, slot)])
If not Self.ready.has_key (Firestamp):
Self.ready.update ([(Firestamp, Box)])
Else
Boxs = Self.ready.get (Firestamp)
Boxs.update (Box)
def _delfromreadylist (self, slot):
Boxs = Self.ready.get (Slot.fire)
Try
box = Boxs.pop (slot.id)
If not boxs:
Self.ready.pop (Slot.fire)
Except (Attributeerror, Keyerror):
Raise Cancelfail
"" "Inside" ""
def _start (self):
Global Timerstamp
Try
Self.firestamp = sorted (Self.ready.keys ()) [0]
Stamp = Float ((Timerstamp + self.firestamp-int (time.time () *1000))/1000
Except Indexerror:
Self.firestamp = Self.nofire
Stamp = Self.nofire
Try
Self.timer.cancel ()
Except Attributeerror:
Pass
Self.timer = Timer (stamp, Self.hander)
Self.timer.start ()
def hander (Self, *args, **kwargs):
"" "Find time arrive slot, do it function" ""
Self.lock.acquire ()
Try
Boxs = Self.ready.pop (Self.firestamp)
Slots = Boxs.values ()
Except Keyerror:
slots = []
For slots in Slots:
If Slot.period:
SLOT.PC + = 1
If slot.pc! = Slot.period:
Slot.fire = Slot.interval + slot.fire
Self._addtoreadylist (slot, Slot.fire)
elif Slot.period = =-1:
Slot.fire = Slot.interval + slot.fire
Self._addtoreadylist (slot, Slot.fire)
""" """
Self._start ()
Self.lock.release ()
For slots in Slots:
Try
Slot.function (Slot.args, Slot.kwargs)
Except Exception:
Print "Slot ID%s, timer function fail"% slot.id
"" "Operate new timer manager itself" ""
def stop (self):
Self.timer.cancel ()
"" "New Timer Manager" "
def add (self, period=0, interval=1, Function=none, args=[], kwargs={}):
"""
Period:one time = 0, times = >0, always = 1
Interval:timer Fire Relative Timerreference
Function:when Timer fire, call back function
Args,kwargs:callback function args
"""
interval = Int (interval) * self.resolution#seconds
If Interval < self.resolution:
Interval = self.resolution
Slot = slot (period, interval, function, *args, **kwargs)
box = Dict ([(Slot.id, slot)])
Self.wait.update (Box)
Return slot
def remove (self, slot):
If Isinstance (slot, slot):
Self.cancel (slot)
Try
Self.wait.pop (slot.id)
Except Keyerror:
Print "Wait dict not have the cancel timer"
"" "Timer API" ""
def reset (self, slot):
If Isinstance (slot, slot):
Self.cancel (slot)
slot.pc = 0
Self.start (slot)
def start (self, slot):
def Newtimerstamp (Timebase, resolution):
nowoffset = Int (Time.time () * +)-timebase
If Nowoffset% resolution < RESOLUTION/10:
Currentstamp = Nowoffset/resolution
Else
Currentstamp = (Nowoffset + resolution-1)/Resolution
Return Currentstamp * 1000
Global Timerstamp
If Isinstance (slot, slot):
Firestamp = Slot.interval + Newtimerstamp (Timerstamp, self.resolution)
Slot.fire = Firestamp
Self.lock.acquire ()
Self._addtoreadylist (slot, Firestamp)
If Self.firestamp > Slot.fire:
Self._start ()
Self.lock.release ()
def cancel (self, slot):
If Isinstance (slot, slot):
Try
Self.lock.acquire ()
Self._delfromreadylist (slot)
Self._start ()
Self.lock.release ()
Except Cancelfail:
Self.lock.release ()
def hello (*args, **kargs):
Print Args[0], Datetime.datetime.now ()
if __name__ = = "__main__":
Print "Start test Timer", Datetime.datetime.now ()
NT = Newtimer (500)
T0 = Nt.add (-1, 5, Hello, [0])
T1 = Nt.add (4, 7, Hello, [1])
t2 = Nt.add (1, 3, Hello, [2]) #
T3 = Nt.add (1, 4, Hello, [3]) #
T4 = Nt.add (4, 5, Hello, [4])
T5 = Nt.add (5, Hello, [5]) #
T6 = Nt.add (9, 7, Hello, [6])
T7 = Nt.add (1, 8, Hello, [7]) #
T8 = Nt.add (1, Hello, [8])
Nt.start (t0)
Nt.start (T1)
Nt.start (T2) #
Nt.start (T3) #
Nt.start (T4)
Nt.start (T5) #
Nt.start (T6)
Nt.start (T7) #
Nt.start (T8)
Nt.cancel (T2)
Nt.cancel (T3)
Nt.remove (T5)
Nt.remove (T3)
Time.sleep (3)
Nt.start (T2)
Nt.cancel (T8)
Time.sleep (300)
Nt.stop ()
Print "Finish test Timer", Datetime.datetime.now ()