b EThread::process_event
b NetHandler::mainNetEvent epoll_wait 获取结果放入NetHandler队列 然后遍历弹出read_ready_list队列得到UnixNetVConnection类型的一个vc 然后调用vc->net_read_io
b UnixNetVConnection::net_read_io 一行就是read_from_net
b UnixNetVConnection.cc:read_from_net 调用socketManager.read获取一手信息 一旦读完数据 此函数将调用read_signal_and_update
b UnixNetVConnection.cc:read_signal_and_update 此函数将回调状态机UnixNetVConnection中的read.vio的handleEvent() 即下面的函数
b ProtocolProbeSessionAccept.cc:ioCompletionEvent 先判断协议scheme 在switch_case io ready/complete/timeout事件
然后此函数将调用accept b HttpSessionAccept::accept
b NetHandler::mainNetEvent
b UnixNetVConnection::net_read_io
b UnixNetVConnection.cc:read_from_net
b UnixNetVConnection.cc:read_signal_and_update
b ProtocolProbeSessionAccept.cc:ioCompletionEvent
b HttpSessionAccept::accept
事件处理机制
EThread中只有两个队列 内/外部队列, 外部队列中有个子队列即本地队列 在process_event中又有个临时队列即隐性队列
内/外部队列又称保护/优先级队列 本地队列只能被当前线程访问
在process_event中 先拿事件的锁 拿不到事件的锁则放回本地队列 拿到了则就回调e->continuation->handleEvent(calling_code, e);
执行完后 再看事件是否是周期性事件(period为周期) 若事件是周期事件则计算下一次时间timeout_at 然后再放入本地队列
for(;;)
先遍历外部本地队列(目的 优先处理立即执行事件)
事件的timeout_at为0 即为immediate立即执行process_event
timeout_at>0 即为interval周期执行 放入内部队列
timeout_at<0 即为negative隐性事件 放入隐性队列
遍历内部队列(时间优先级)
按时间算法 process_event
遍历隐性队列
把外部队列所有事件放入本地队列
触发signals,向其它线程通知事件 ??????没看懂
再次遍历外部本地队列 (目的 优先处理立即执行事件)
...
执行隐性队列polling事件 取出一个事件 通过process_event呼叫状态机(TCP,状态机是NetHandler::mainNetEvent)
把外部队列所有事件放入本地队列
外部队列中的事件由EThread提供的9个schedule_*函数完成
gdb调试得到以下结论:
HttpSM::main_handler 相当于mainEvent()里面调用了HttpSM::do_http_server_open 返回action
里面调用了NetProcessor::connect_re 并返回action
里面调用了UnixNetProcessor::connect_re_internal(httpsm, ...)
从httpsm中获取当前线程 并初始化一个具体的task状态机--UnixNetVConnection *vc
vc->handler是UnixNetVConnection::startEvent 里面调用了connectUp
vc->mainEvent里面也调用了handleEvent,注意mainEvent只被event-system调用
vc->action赋值为sockEntry
vc->mutex赋值为httpsm中的mutex
取sockEntry中的互斥量加锁
取@#$#@加锁
若加锁成功则调用vc->connectUp
否则选择一个新的线程 放入其事件池中调度 eventProcessor.schedule_imm(vc, opt->etype); 直到事件到来 调用vc的mainEvent