`
chenyinghg
  • 浏览: 33744 次
  • 性别: Icon_minigender_2
  • 来自: 惠州
社区版块
存档分类
最新评论

tornado.util.Configurable

 
阅读更多

tornado.util.Configurable是tornado.ioloop.IOLoop的基类,使用了元类编程的方式,重写了__new__函数, 改变了其创建类的方式。在此, 只是记载一下其类的初始化调用过程。

 

def __new__(cls, *args, **kwargs):
    base = cls.configurable_base() #这个函数必须要求在子类中实现,结合下面的代码,个人理解是在修改最终要初始化的类。如果返回值并不是当前new的类,就不必瞎折腾了。
    init_kwargs = {}
    if cls is base:
        impl = cls.configured_class() #这个函数实现就在Configurable中,主要是调用了子类的configurable_default函数。该函数就返回了最终要初始化的类
        if base.__impl_kwargs:
            init_kwargs.update(base.__impl_kwargs)
    else:
        impl = cls
    init_kwargs.update(kwargs)
    instance = super(Configurable, cls).__new__(impl)
    instance.initialize(*args, **init_kwargs)  #调用需要初始化类的initialize
    return instance

@classmethod
def configured_class(cls):
    base = cls.configurable_base()
    if cls.__impl_class is None:
        base.__impl_class = cls.configurable_default()
    return base.__impl_class

以IOLoop为例:

@classmethod
def configurable_default(cls):
    if hasattr(select, "epoll"):  # Linux
        from tornado.platform.epoll import EPollIOLoop
        return EPollIOLoop
    if hasattr(select, "kqueue"):   # BSD or Mac
        from tornado.platform.kqueue import KQueueIOLoop
        return KQueueIOLoop
    from tornado.platform.select import SelectIOLoop  #如果都不行, 那就只能用select了
    return SelectIOLoop
@staticmethod
def instance():
    if not hasattr(IOLoop, "_instance"): #单例模式
        with IOLoop._instance_lock:  #避免同时初始化
            if not hasattr(IOLoop, "_instance"): #再判断一次, 保证真的只是单例的
                IOLoop._instance = IOLoop()
    return IOLoop._instance

def initialize(self, make_current=None): #make_current看起来像是在标识是不是要强制创建
    if make_current is None:
        if IOLoop.current(instance=False) is None:
            self.make_current()
    elif make_current:
        if IOLoop.current(instance=False) is not None: #已经初始化过了?
            raise RuntimeError("current IOLoop already exists")
        self.make_current()

def make_current(self):
    IOLoop._current.instance = self

 

 

本人使用的系统是ubuntu,所以最后返回的是EPollIOLoop。

 

def initialize(self, **kwargs):
    super(EPollIOLoop, self).initialize(impl=select.epoll(), **kwargs) #由于EPollIOLoop是PollIOLoop的子类,所以又需要定位到父类查看了

 PollIOLoop:

def initialize(self, impl, time_func=None, **kwargs):
    super(PollIOLoop, self).initialize(**kwargs)
    self._impl = impl
    if hasattr(self._impl, 'fileno'):
        set_close_exec(self._impl.fileno())
    self.time_func = time_func or time.time
    self._handlers = {}
    self._events = {}
    self._callbacks = []
    self._callback_lock = threading.Lock()
    self._timeouts = []
    self._cancellations = 0
    self._running = False
    self._stopped = False
    self._closing = False
    self._thread_ident = None
    self._blocking_signal_threshold = None
    self._timeout_counter = itertools.count()

    self._waker = Waker()
    self.add_handler(self._waker.fileno(),   #这里只是将读的一段加入。源注释是说创建Pipe, 在需要的时候唤醒IOLoop。另一端在那里??
                     lambda fd, events: self._waker.consume(),
                     self.READ)

def add_handler(self, fd, handler, events):
    fd, obj = self.split_fd(fd)
    self._handlers[fd] = (obj, stack_context.wrap(handler))
    self._impl.register(fd, events | self.ERROR)

def split_fd(self, fd):
    try:
        return fd.fileno(), fd
    except AttributeError:
        return fd, fd

def close(self, all_fds=False):
    with self._callback_lock:
        self._closing = True
    self.remove_handler(self._waker.fileno()) #先pop出来, 最后才close
    if all_fds:
        for fd, handler in self._handlers.values():
            self.close_fd(fd)
    self._waker.close()
    self._impl.close()
    self._callbacks = None
    self._timeouts = None

 

Waker

class Waker(interface.Waker):  #pipe的方式
    def __init__(self):
        r, w = os.pipe()
        _set_nonblocking(r)
        _set_nonblocking(w)
        set_close_exec(r)
        set_close_exec(w)
        self.reader = os.fdopen(r, "rb", 0)
        self.writer = os.fdopen(w, "wb", 0)

    def fileno(self):
        return self.reader.fileno()

    def write_fileno(self):
        return self.writer.fileno()

    def wake(self):
        try:
            self.writer.write(b"x")
        except IOError:
            pass

    def consume(self):
        try:
            while True:
                result = self.reader.read()
                if not result:
                    break
        except IOError:
            pass

    def close(self):
        self.reader.close()
        self.writer.close()

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics