Python定时器的一个实现

'''
Created on 2012-10-11

@author: blh
'''

import threading
import time

class PyTimer:
    PRECISION = 10  # 10ms
    
    def __init__(self, scheduler_num=1):
        self.lock = threading.Lock()
        self.schedulers = []
        self.scheduler_index = 0
        self.scheduler_num = scheduler_num

    def get_scheduler(self):    
        self.lock.acquire()
        index = self.scheduler_index
        self.scheduler_index = (self.scheduler_index + 1) % self.scheduler_num
        self.lock.release()
        return self.schedulers[index]

    def create(self, callback):
        return self.Timer(self, callback)
        
    def start(self):
        n = 0
        while n < self.scheduler_num:
            scheduler = self.Scheduler(n)
            scheduler.start()
            self.schedulers.append(scheduler)
            n += 1

    def stop(self):
        for scheduler in self.schedulers:
            scheduler.stop()
        
    def get_info(self):
        info = ''
        total = 0
        n = 1
        for scheduler in self.schedulers:
            count = scheduler.get_count()
            info += 'timer-{0}: {1}\n'.format(n, count)
            total += count
            n += 1
        info += 'timer total: {0}\n'.format(total)
        return info        
    
    class Timer:
        def __init__(self, manager, callback):
            self.manager = manager
            self.callback = callback
            self.scheduler = None
            self.timeout = True                   
    
        #intval unit is ms
        def set(self, intval):
            self.intval = int(intval / PyTimer.PRECISION)
            self.scheduler = self.manager.get_scheduler()            
            self.scheduler.set(self)
        
        def cancel(self):
            if self.scheduler:
                self.scheduler.cancel(self)

        def reset(self, intval):
            self.cancel()
            self.set(intval)
            
    class Scheduler(threading.Thread):                               
        QUEUE_NUM = 300

        def __init__(self, scheduler_id):
            threading.Thread.__init__(self)
            self.scheduler_id = scheduler_id
            self.lock = threading.Lock()
            self.queues = {}
            self.timers = {}
            self.current = 0
            self.running = True
            for n in range(self.QUEUE_NUM):
                self.queues[n] = []
        
        def get_offset(self, intval):
            offset = intval
            if offset >= self.QUEUE_NUM:
                offset = (self.QUEUE_NUM - 1)
            return offset
        
        def get_queue(self, offset):
            qid = (self.current + offset) % self.QUEUE_NUM
            return self.queues[qid]

        def enqueue(self, timer):
            offset = self.get_offset(timer.intval)
            timer.intval -= offset
            queue = self.get_queue(offset)
            self.timers[timer] = queue
            queue.append(timer)
        
        def dequeue(self, timer):
            if self.timers.has_key(timer):
                queue = self.timers.pop(timer)
                queue.remove(timer)
            
        def set(self, timer):
            assert(timer)
            self.lock.acquire()
            self.enqueue(timer)
            self.lock.release()
            return timer
        
        def cancel(self, timer):
            self.lock.acquire()
            self.dequeue(timer)
            self.lock.release()    
        
        def stop(self):
            self.running = False
        
        def run(self):
            base_time = float(PyTimer.PRECISION) / 1000
            sleep_time = base_time
            while self.running:
                if sleep_time > 0.0:
                    time.sleep(sleep_time)
                t1 = time.time()
                self.lock.acquire()
                queue = self.queues[self.current]
                while len(queue):
                    timer = queue.pop()
                    if timer.intval:
                        self.enqueue(timer)
                    else:
                        self.timeout(timer)
                self.current = (self.current + 1) % self.QUEUE_NUM
                self.lock.release()
                t2 = time.time()
                sleep_time = base_time - (t2 - t1)
            
        def timeout(self, timer):
            self.timers.pop(timer)
            self.lock.release()
            timer.callback()
            self.lock.acquire()

        def get_count(self):
            self.lock.acquire()
            count = len(self.timers)
            self.lock.release()
            return count

class TimerDemo:
    def __init__(self):
        self.timer = PyTimer()
        self.timer.start()
    
    def test(self):
        self.t1 = self.timer.create(self.timeout1s)
        self.t1.set(1000)
        self.t2 = self.timer.create(self.timeout3s)
        self.t2.set(3000)
        self.t3 = self.timer.create(self.timeout600ms)
        self.t3.set(600)


    def timeout1s(self):
        print 'timeout1s'
        self.t1.set(1000)
    
    def timeout3s(self):
        print 'timeout3s'
        self.t2.set(3000)
    
    def timeout600ms(self):
        print 'timeout600ms'
        self.t3.set(600)


if __name__ == '__main__':
    demo = TimerDemo()
    demo.test()
   

阅读更多
换一批

没有更多推荐了,返回首页