关于reactor的内部机制(浅析) -- dreamingk [2004-08-09 02:21:09]

刚才向hd讨教了一些关于reactor的问题,受益非浅,这里把它写下来。

1. 精髓描述

reactor内部有一个event loop, 根据事件的类型,

调用不同的事件响应函数,这些函数是事先注册的callback object.

1.1. 详细

::

   1 register_event(event1, fun1)  #这里简化了,twisted是用继承类,重载类函数来完成的
   2 register_event(event2, fun2)
   3 
   4 #event_loop:
   5 while(True):
   6     event = get_event(); #从事件队列里面取事件
   7     switch(event):
   8         case event1:
   9             fun1()
  10         case event2:
  11             fun2()
  12     ....
  • 这里调用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

1.2. 后记体会

这里其实和UI框架中的主事件循环很象,只是各种框架的响应事件的机制不同,MFC是用映射表,Java的swing使用interface,跟twisted有些象,qt使用的是信号/信号槽机制,各有利弊吧。

这些道理其实很简单,俺只是以为twisted为每个连接开一线程呢,所以不知道为什么要用deffered。