@classmethod defconfigurable_default(cls): if hasattr(select, "epoll"): from tornado.platform.epoll import EPollIOLoop return EPollIOLoop if hasattr(select, "kqueue"): # Python 2.6+ on BSD or Mac from tornado.platform.kqueue import KQueueIOLoop return KQueueIOLoop from tornado.platform.select import SelectIOLoop return SelectIOLoop
class IOLoop(Configurable):IOLoop继承了Configurable类,Configurable类的__new__方法调用了configured_class方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
def__new__(cls, *args, **kwargs): base = cls.configurable_base() init_kwargs = {} if cls is base: impl = cls.configured_class() if base.__impl_kwargs: init_kwargs.update(base.__impl_kwargs) else: impl = cls init_kwargs.update(kwargs) instance = super(Configurable, cls).__new__(impl) # initialize vs __init__ chosen for compatibility with AsyncHTTPClient # singleton magic. If we get rid of that we can switch to __init__ # here too. instance.initialize(*args, **init_kwargs) return instance
configured_class方法又调用了configurable_default方法:
1 2 3 4 5 6 7 8
@classmethod defconfigured_class(cls): # type: () -> type """Returns the currently configured class.""" base = cls.configurable_base() if cls.__impl_class isNone: base.__impl_class = cls.configurable_default() return base.__impl_class
所以当初始化一个IOLoop实例的时候就给IOLoop做了配置,根据不同平台选择合适的驱动。
1.3.2 IOLoop实例化
下面我们来看IOLoop的实例化函数:
1 2 3 4 5 6 7 8 9 10
# Global lock for creating global IOLoop instance _instance_lock = threading.Lock() @staticmethod definstance(): ifnot hasattr(IOLoop, "_instance"): with IOLoop._instance_lock: ifnot hasattr(IOLoop, "_instance"): # New instance after double check IOLoop._instance = IOLoop() return IOLoop._instance
很显然,这里是实现了一个全局的单例模式。确保多个线程也只有一个IOLoop实例。(思考一下:为什要double check?if not hasattr(IOLoop, "_instance") ^_^)