|
单线程实现多个定时器
NewTimer.py 复制代码 代码如下: #!/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 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) 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,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,**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 has the cancel timer"
""" timer api """ def reset(self,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): 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,[1]) t2 = nt.add( 1,3,[2])# t3 = nt.add( 1,4,[3])# t4 = nt.add( 4,[4]) t5 = nt.add( 12,[5])# t6 = nt.add( 9,[6]) t7 = nt.add( 1,8,[7])# t8 = nt.add( 40,1,[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()
(编辑:安卓应用网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|