##language:zh ''' 关于reactor的内部机制(浅析) ''' -- dreamingk [<>] <> ''刚才向hd讨教了一些关于reactor的问题,受益非浅,这里把它写下来。'' = 精髓描述 = ''reactor内部有一个event loop, 根据事件的类型, 调用不同的事件响应函数,这些函数是事先注册的callback object.'' == 详细 == :: {{{ #!python register_event(event1, fun1) #这里简化了,twisted是用继承类,重载类函数来完成的 register_event(event2, fun2) #event_loop: while(True): event = get_event(); #从事件队列里面取事件 switch(event): case event1: fun1() case event2: fun2() .... }}} * 这里调用fun1,fun2是阻塞调用的,就是说只有fun1执行完才能接着下一次loop,这样如果fun1执行的时间太长, 事件就会阻塞在事件队列里面。 而实际项目中,fun1,fun2很难保证能马上返回,可能要查询数据库什么的,因此这里必须想办法,比如多线程什么的,而twisted提供了deffered对象来提供帮助。 {{{ 在Cpython中,reactor对网络数据的读写是用select实现的,每个需要回调的对象都是abstract.FileDescriptor派生类的实例。该对象 实现了fileno方法,以返回fd供select用,还要实现了doWrite和doRead方法供回调。该对象的startReading,startWriting方法会将回调的 对象加入到reactor的读写队列中(实际在reactor中是dict)。当reactor的主循环工作时,它首先去检查那些用Calllator登记过的函数是否到 了时间,如到了就运行它们,然后调用select,并将读写队列中的对象传递给它,此外还需根据CallLater函数队列中的时间设置一个合适的超时。 当select返回时,再根据返回的结果调用相应对象的doRead,doWrite方法。 此外,如上面提到的,CallLater函数可以将函数登记到回调队列中。 ---0.706 }}} == 后记体会 == 这里其实和UI框架中的主事件循环很象,只是各种框架的响应事件的机制不同,MFC是用映射表,Java的swing使用interface,跟twisted有些象,qt使用的是信号/信号槽机制,各有利弊吧。 这些道理其实很简单,俺只是以为twisted为每个连接开一线程呢,所以不知道为什么要用deffered。