TNonblockingServer的I/O线程是TNonblockingIOThread对象。每个TNonblockingIOThread保存服务的server指针,同时记录监听的套接字。他并不是真正的pthread,所以线程号是额外指定的,在构造方法中指定。

TNonblockingIOThread注册两类事件,一类是监听套接字,回调函数注册为TNonblockingIOThread::listenHandler,上下文是server_指针;一类是监听管道,用于通信,回调函数注册为TNonblockingIOThread::notifyHandler,上下文是this指针。该管道非阻塞,并且不能为子进程复用。registerEvents用于注册,notify用于通知,也就是向管道的写入端写入数据,内容是TConnection指针。每当一个Task执行完成,都要调用notify通知线程。另外,程序可以通过notify一个空指针,终止目标TNonblockingIOThread。

listenHandler是调用server_->workSocket方法,发起接收数据。

一旦任何管道有事件发生,libevent会启用notifyHandler接收数据。如果接收到合法的TConnection指针,说明Task完成,调用TConnection->transition,将状态机切换到“回送结果”。如果接收的结果是非法的数据,说明发生了错误,将故障的TNonBlockingIOThread终止(调用breakLoop方法)。如果接收到的结果是0,说明对端已经关闭了连接,即线程可能已经终止。如果没有数据可以接收,那么直接跳出这个回调函数,下次有数据可以接收时,libevent会重新调用这个回调函数。需要注意的是,尽管是非阻塞套管道套接字,仅仅接收到了数据是0,并不意味着一切正常而仅是没有数据可以接收。如果是没有数据可以接收但是一切正常,recv的结果应该是负值,并且errno会设置成EWOULDBLOCK或者EAGAIN。

breakLoop,如果是异常调用,程序直接退出(abort)。如果是正常调用,首先event_base_loopbreak,其次向目标TNonblockingIOThread发送notify(NULL)

run是TNonblockingIOThread的基本线程体。先生成event_base,然后注册监听事件,即刚刚指明的两个事件:管道和套接字。然后按需设置线程调度的优先级(可以先忽略这段逻辑),event_base_loop。线程将阻塞在这里,直到被event_base_loopbreak。这样,一个长期运行的IO线程就启动了。整个I/O流程开始由各种回调处理,以及发起下一次流程。