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

twisted reactor calllater实现的更多相关文章

  1. (三)认识twisted reactor

    一.reactor是单线程模型,简单粗暴,也就是说网络IO和我们的业务逻辑一般是在一个线程里,其中网络IO通过event loop的方式去异步执行,效率也很高.看下官网的这幅图,比较清晰 twiste ...

  2. twisted reactor分析

    调用reactor.run(),就会调用到mainloop函数,从而调用到select或epoll,监控fd的读写. posixbase.py: def listenTCP(self, port, f ...

  3. twisted reactor 实现源码解析

    twisted reactor 实现源码解析 1.      reactor源码解析 1.1.    案例分析代码: from twisted.internet import protocol fro ...

  4. twisted reactor执行流程

    #reactorbase的主循环 def mainLoop(self): while self._started: try: while self._started: # Advance simula ...

  5. Python Twisted、Reactor

    catalogue . Twisted理论基础 . 异步编程模式与Reactor . Twisted网络编程 . reactor进程管理编程 . Twisted并发连接 1. Twisted理论基础 ...

  6. 理解twisted中的reactor和deferred(二)

    Deferred可以添加多个回调函数,每个回调函数的结果作为下一个回调函数的参数 代码实例(可在pycharm中运行,摘自 https://twistedmatrix.com/documents/cu ...

  7. 理解twisted中的reactor和deferred(一)

    Deferred是一个延迟加载对象,这个概念类似于tornado future,是调用异步操作返回的一个对象,其中包括了操作成功后的回调处理,错误后的回调处理. 简单讲,当我们需要执行一个耗时操作,比 ...

  8. 笔记-twisted源码-import reactor解析

    笔记-twisted源码-import reactor解析 1.      twisted源码解析-1 twisted reactor实现原理: 第一步: from twisted.internet ...

  9. Python中reactor,factory,protocol

    最为简单的情况下,除了了解清reactor的简单使用,你还要了解Protocol和Factory.它们最终都会由reactor的侦听建立和run来统一调度起来. 建立服务器的第一个要解决的问题就是服务 ...

随机推荐

  1. Django框架中auth模块的详解

    auth模块 auth模块是对登录认证方法的一种封装,本身就是一个对象,可以获取用户的详细信息,有了auth模块可以验证登录信息是否存在数据库中,还可以检验用户是否已经登录,校验密码等 auth方法 ...

  2. CF1288F Red-Blue Graph

    Link 考虑上下界+费用流. 对于左部点\(u\): 如果颜色为\(B\),连\((s,u,[1,+\infty),0)\). 如果颜色为\(R\),连\((u,t,[1,+\infty),0)\) ...

  3. jquery grid 获取选中的行的数据,以及获取所有行的方法

    https://blog.csdn.net/shenqingkeji/article/details/52861319

  4. leetcode 72.编辑距离(dp)

    链接:https://leetcode-cn.com/problems/edit-distance/submissions/ 设dp[i][j]表示串s1前i个字符变换成串s2前j个字符所需要的最小操 ...

  5. imread函数+cvtColor()函数

    加载图像(用cv::imread) imread功能是加载图像文件成为一个Mat对象,其中第一个参数表示图像文件名称 第二个参数,表示加载的图像是什么类型,支持常见的三个参数值 IMREAD_UNCH ...

  6. n个点m条有向边,求在入度为零的点到n号点的所有路 //径中,哪条边被这些路径覆盖的次数最多

    //n个点m条有向边,求在入度为零的点到n号点的所有路 //径中,哪条边被这些路径覆盖的次数最多 //有关DAG的知识,先记个模板 #include<iostream> #include& ...

  7. 主席树 hdu 4348

    题意:有一个由n个数组成的序列,有4中操作: 1.C l r d [l,r]这段区间都加上d 2.Q l r 询问[l,r]这段区间的和 3.H l r t 询问之前t时间[l,r]的区间和 4.B ...

  8. C语言 exit

    C语言 exit 在main函数中调用exit和return结果是一样的,但在子函数中调用return只是代表子函数终止了,在子函数中调用exit,那么程序终止. 案例 #include <st ...

  9. OO博客作业-《JML之卷》

    OO第三单元小结 一.JML语言理论基础以及应用工具链情况梳理 一句话来说,JML就是用于对JAVA程序设计逻辑的预先约定的一种语言,以便正确严格高效地完成程序以及展开测试,这在不能容忍细微错误的工程 ...

  10. go基础_切片

    切片创建方式 1.通过数组创建 2.通过内置函数make创建 切片允许的操作 1.追加元素 2.通过内置函数make创建 package main import "fmt" fun ...