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 什麼的。。
#歇一下子。。