twisted reactor calllater实现

twisted reactor calllater实现

1.      calllater实现代码

测试源码:

from twisted.internet import reactor
from twisted.internet import defer

 

def func_1():
    print('calllater测试')
    time.sleep(5)
    print('calllater结束')

 


# error handle
def test_deferred_a():
    #d = test_retrurn_deferred()
   
reactor.callLater(4, func_1)
   
reactor.callLater(15, reactor.stop)
    reactor.run()

if __name__ == '__main__':
    test_deferred_a()

 

1.1.    第一步:调用calllater

reactor.callLater(3, d.callback, 8)

先找到calllater

# <twisted.internet.selectreactor.SelectReactor object at 0x000000CE3BFC72B0>
@implementer(IReactorCore, IReactorTime, IReactorPluggableResolver,
             IReactorPluggableNameResolver, _ISupportsExitSignalCapturing)
class ReactorBase(object):
    """
    Default base class for Reactors.
    """
   
def callLater(self, _seconds, _f, *args, **kw):
        """See twisted.internet.interfaces.IReactorTime.callLater.
        """
       
assert callable(_f), "%s is not callable" % _f
        assert _seconds >= 0, \
               "%s is not greater than or equal to 0 seconds" % (_seconds,)
        tple = DelayedCall(self.seconds() + _seconds, _f, args, kw,
                           self._cancelCallLater,
                           self._moveCallLaterSooner,
                           seconds=self.seconds)
        self._newTimedCalls.append(tple)
        return tple

DelayedCall基本上可以把它当作一个中间类,用于保存一些信息。

结果就是向self._newTimedCalls添加一个定时调用

self._newTimedCalls.append(tple)

可以看一下它的具体内容

_newTimedCalls= <class 'list'>: [<twisted.internet.base.DelayedCall object at 0x000000CE3C2EA668>]

 

1.2.    第二步

reactor.run()

跳过一些前置处理内容,直接到mainloop

def mainLoop(self):
    while self._started:
        try:
            while self._started:
                # Advance simulation time in delayed event
                # processors.
               
self.runUntilCurrent()
                t2 = self.timeout()
                t = self.running and t2
                self.doIteration(t)
        except:
            log.msg("Unexpected error in main loop.")
            log.err()
        else:
            log.msg('Main loop terminated.')

 

进入self.runUntilCurrent()

def runUntilCurrent(self):
    """

        运行所有挂起的calls
    Run all pending timed calls.
    """
   
if self.threadCallQueue:
        # Keep track of how many calls we actually make, as we're
        # making them, in case another call is added to the queue
        # while we're in this loop.
        
count = 0
        total = len(self.threadCallQueue)
        for (f, a, kw) in self.threadCallQueue:
            try:
                f(*a, **kw)
            except:
                log.err()
            count += 1
            if count == total:
                break
        del
self.threadCallQueue[:count]
        if self.threadCallQueue:
            self.wakeUp()

    # insert new delayed calls now
   
self._insertNewDelayedCalls()

 

now = self.seconds()
while self._pendingTimedCalls and (self._pendingTimedCalls[0].time <= now):
    call = heappop(self._pendingTimedCalls)
    if call.cancelled:
        self._cancellations-=1
        continue

    if
call.delayed_time > 0:
        call.activate_delay()
        heappush(self._pendingTimedCalls, call)
        continue

    try
:
        call.called = 1
        call.func(*call.args, **call.kw)
    except:
        log.deferr()
        if hasattr(call, "creator"):
            e = "\n"
           
e += " C: previous exception occurred in " + \
                 "a DelayedCall created here:\n"
           
e += " C:"
           
e += "".join(call.creator).rstrip().replace("\n","\n C:")
            e += "\n"
           
log.msg(e)


if (self._cancellations > 50 and
    
self._cancellations > len(self._pendingTimedCalls) >> 1):
    self._cancellations = 0
    self._pendingTimedCalls = [x for x in self._pendingTimedCalls
                               if not x.cancelled]
    heapify(self._pendingTimedCalls)

if self._justStopped:
    self._justStopped = False
   
self.fireSystemEvent("shutdown")

 

 

进入self._insertNewDelayedCalls()

def _insertNewDelayedCalls(self):
    for call in self._newTimedCalls:
        if call.cancelled:
            self._cancellations-=1
        else:
            call.activate_delay()
            heappush(self._pendingTimedCalls, call)
    self._newTimedCalls = []

从self._newTimedCalls中获取DelayedCall()实例,放入self._pendingTimedCalls

 

在runUntilCurrent中会调用self._pendingTimedCallsk列表相关对象,也就是执行func_1.

 

2.      其它

2.1.    代码解析1

heappush(self._pendingTimedCalls, call)

 

函数heappush源自heapq.py

def heappush(heap, item):
    """Push item onto heap, maintaining the heap invariant."""
   
heap.append(item)
    _siftdown(heap, 0, len(heap)-1)

简单点说,它会构建一个有序堆,默认最小堆。

 

 

在构建有序堆过程中肯定是要比较int类型了,但call是一个类。

这里要回顾python类的特殊方法了,已有文档,不赘述。

call是DelayedCall类的实例,查看相关代码。

def __le__(self, other):
    """
    Implement C{<=} operator between two L{DelayedCall} instances.

    Comparison is based on the C{time} attribute (unadjusted by the
    delayed time).
    """
   
return self.time <= other.time


def __lt__(self, other):
    """
    Implement C{<} operator between two L{DelayedCall} instances.

    Comparison is based on the C{time} attribute (unadjusted by the
    delayed time).
    """
   
return self.time < other.time

 

转载于:https://www.cnblogs.com/wodeboke-y/p/11247077.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值