Multiple timers are implemented in a single thread.
NewTimer. py
Copy codeThe Code is 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 #1 s
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)
Failed T (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
Failed t IndexError:
Self. firestamp = self. nofire
Stamp = self. nofire
Try:
Self. timer. cancel ()
T 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 ()
Failed t KeyError:
Slots = []
For slot 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 slot in slots:
Try:
Slot. function (slot. args, slot. kwargs)
Failed t 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)
Failed t KeyError:
Print "wait dict not has 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 () * 1000)-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 ()
Failed t 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 (0, 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 (12, 5, hello, [5]) #
T6 = nt. add (9, 7, hello, [6])
T7 = nt. add (1, 8, hello, [7]) #
T8 = nt. add (40, 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 ()