twisted internet.reactor部分 源碼分析

twisted.internet.reactor 是進行全部twisted事件循環的地方。python

reactor在1個python進程中只能有一個。react

在windows下用的是select。linux下epool。mac下是pool,這點和socketserver,tornado的都同樣哈()。linux

源碼位於twisted.internet.default._getInstallFunctionwindows

    try:
        if platform.isLinux():
            try:
                from twisted.internet.epollreactor import install
            except ImportError:
                from twisted.internet.pollreactor import install
        elif platform.getType() == 'posix' and not platform.isMacOSX():
            from twisted.internet.pollreactor import install
        else:
            from twisted.internet.selectreactor import install
    except ImportError:
        from twisted.internet.selectreactor import install
    return install

看SelectReactor緩存

 

try:
from twisted.internet.win32eventreactor import _ThreadedWin32EventsMixin
except ImportError:
_extraBase = object
else:
_extraBase = _ThreadedWin32EventsMixin

  

@implementer(IReactorFDSet)
class SelectReactor(posixbase.PosixReactorBase, _extraBase):
    """
    A select() based reactor - runs on all POSIX platforms and on Win32.

    @ivar _reads: A set containing L{FileDescriptor} instances which will be
        checked for read events.

    @ivar _writes: A set containing L{FileDescriptor} instances which will be
        checked for writability.
    """
    balabala........

主要功能實如今posixbase.PosixReactorBase這個類。而後根據os的不一樣,混入不一樣的多線程mixin。多線程

每種Reactor要實現IReactorFDSet的接口。接口定義的是管理 端口狀態的方法。好比addReader,addWriter。。仍是放代碼吧。socket

class IReactorFDSet(Interface):
    """
    Implement me to be able to use L{IFileDescriptor} type resources.

    This assumes that your main-loop uses UNIX-style numeric file descriptors
    (or at least similarly opaque IDs returned from a .fileno() method)
    """

    def addReader(reader):
        """
        I add reader to the set of file descriptors to get read events for.

        @param reader: An L{IReadDescriptor} provider that will be checked for
                       read events until it is removed from the reactor with
                       L{removeReader}.

        @return: C{None}.
        """

    def addWriter(writer):
        """
        I add writer to the set of file descriptors to get write events for.

        @param writer: An L{IWriteDescriptor} provider that will be checked for
                       write events until it is removed from the reactor with
                       L{removeWriter}.

        @return: C{None}.
        """

    def removeReader(reader):
        """
        Removes an object previously added with L{addReader}.

        @return: C{None}.
        """

    def removeWriter(writer):
        """
        Removes an object previously added with L{addWriter}.

        @return: C{None}.
        """

    def removeAll():
        """
        Remove all readers and writers.

        Should not remove reactor internal reactor connections (like a waker).

        @return: A list of L{IReadDescriptor} and L{IWriteDescriptor} providers
                 which were removed.
        """

    def getReaders():
        """
        Return the list of file descriptors currently monitored for input
        events by the reactor.

        @return: the list of file descriptors monitored for input events.
        @rtype: C{list} of C{IReadDescriptor}
        """

    def getWriters():
        """
        Return the list file descriptors currently monitored for output events
        by the reactor.

        @return: the list of file descriptors monitored for output events.
        @rtype: C{list} of C{IWriteDescriptor}
        """

  沒什麼奇怪的地方。。ide

  因此就不看這邊了。這地方太熟了。除去了多線程的Mixin和端口reader,writer的接口,剩下的就是reactor主要部分啦tornado

  接下來看下posixbase.PosixReactorBase這個基類。爲何是PosixReactorBase而不是ReactorBase呢,由於後者是他的父類。。oop

  

@implementer(IReactorTCP, IReactorUDP, IReactorMulticast)
class PosixReactorBase(_SignalReactorMixin, _DisconnectSelectableMixin,
                       ReactorBase):
    """    A basis for reactors that use file descriptors.

    @ivar _childWaker: C{None} or a reference to the L{_SIGCHLDWaker}
        which is used to properly notice child process termination.
    """

    # Callable that creates a waker, overrideable so that subclasses can
    # substitute their own implementation:

 

IReactorTCP, IReactorUDP, IReactorMulticast是定義了PosixReactorBase的套接字方面的一些接口。接口定義的方法很少,源碼中實現的還有ListenSSL,listenUNIX,listenUNIXDatagram,甚至adoptStreamPort去兼容IPV6。。he,真很多。

再繼續分析PosixReactorBase的混入。
1.  _SignalReactorMixin,前面說的單進程只有一個Reactor就是在這裏實現的啦。。

並且reactor也不能在stop後再run起來。Reactor在一個進程中只能run一次。。
二、_DisconnectSelectableMixin。這個MixIn只實現了一個方法。來處理haf_close,原理仍是在於TCP的4次揮手再見。根據是否完成揮手操做,區分ConnectionLost仍是ConnectionDone.

 而後終於看這個ReactorBase類了,抽絲剝繭,最後看到的就是就是這個東西。。

  

  

@implementer(IReactorCore, IReactorTime, IReactorPluggableResolver)
class ReactorBase(object):
    """
    Default base class for Reactors.

    @type _stopped: C{bool}
    @ivar _stopped: A flag which is true between paired calls to C{reactor.run}
        and C{reactor.stop}.  This should be replaced with an explicit state
        machine.

    @type _justStopped: C{bool}
    @ivar _justStopped: A flag which is true between the time C{reactor.stop}
        is called and the time the shutdown system event is fired.  This is
        used to determine whether that event should be fired after each
        iteration through the mainloop.  This should be replaced with an
        explicit state machine.

    @type _started: C{bool}
    @ivar _started: A flag which is true from the time C{reactor.run} is called
        until the time C{reactor.run} returns.  This is used to prevent calls
        to C{reactor.run} on a running reactor.  This should be replaced with
        an explicit state machine.

    @ivar running: See L{IReactorCore.running}

    @ivar _registerAsIOThread: A flag controlling whether the reactor will
        register the thread it is running in as the I/O thread when it starts.
        If C{True}, registration will be done, otherwise it will not be.
    """

  在這裏,實現的是IReactorCore,IReactorTime, IReactorPluggableResolver三個接口。。(核心兩個字寫在臉上了。「打臉」就朝這裏)

  IReactor實現了什麼呢。就是Reacor的主要特色。Event操做。Reactor的開關,和 DNS查詢。。。BTW,這點比BaseHTTPServer想的好多了。

  後者就直接去查DNS了。而這裏放入了事件循環當中,沒有去阻塞進程。。

  IReactorTime是有關defer對象處理,seconds和callLater什麼的。

  IReactorPluggableResolver是提供了關於查詢DNS的接口,方便本身去實現緩存或者預設DNS,本地DNS 什麼的。。

  #歇一下子。。

相關文章
相關標籤/搜索