//注册一个ZCE_Event_Handler到反应器 int ZCE_Reactor::register_handler(ZCE_Event_Handler *event_handler, int event_mask ) { int ret = 0; //如果已经大于最大数量,返回错误 if (handler_map_.size() >= max_event_number_) { return -1; } ZCE_HANDLE socket_hd = event_handler->get_handle(); ZCE_Event_Handler *tmp_handler = NULL; //如果已经存在,不能继续注册 ret = find_event_handler(socket_hd, tmp_handler); if (ret == 0) { ZCE_LOG(RS_ERROR, "[zcelib] [%s] find_event_handler eaqul handle [%lu]. please check you code .", __ZCE_FUNC__, tmp_handler); return -1; } //不检测了,失败了就是命不好 handler_map_.insert(std::make_pair(socket_hd, event_handler)); if (event_mask != 0) { schedule_wakeup(event_handler, event_mask); } return 0; }
//注册一个ZCE_Event_Handler到反应器 int ZCE_Reactor::register_handler(ZCE_Event_Handler *event_handler, int event_mask ) { int ret = 0; //如果已经大于最大数量,返回错误 if (handler_map_.size() >= max_event_number_) { return -1; } ZCE_SOCKET socket_hd = event_handler->get_handle(); ZCE_Event_Handler *tmp_handler = NULL; //如果已经存在,不能继续注册 ret = find_event_handler(socket_hd, tmp_handler); if (ret == 0) { return -1; } //不检测了,失败了就是命不好 handler_map_.insert(std::make_pair(socket_hd, event_handler)); if (event_mask != 0) { schedule_wakeup(event_handler, event_mask); } return 0; }
//从反应器注销一个ZCE_Event_Handler,同事取消他所有的mask //event_mask其实只判断里面的DONT_CALL int ZCE_Reactor::remove_handler(ZCE_Event_Handler *event_handler, bool call_handle_close) { int ret = 0; ZCE_HANDLE ev_hd = event_handler->get_handle(); ZCE_Event_Handler *tmp_handler = NULL; //remove_handler可能会出现两次调用的情况,我推荐你直接调用handle_close ret = find_event_handler(ev_hd, tmp_handler); if (ret != 0) { // 未找到 ZCE_LOG(RS_INFO, "[zcelib][%s] find handle [%lu] fail. my be reclose ?", __ZCE_FUNC__, ev_hd); return -1; } //不好用这个断言保护,因为可能出现一些重复调用等问题 //ZCE_ASSERT_DGB(tmp_handler == event_handler); int event_mask = event_handler->get_mask(); //如果有mask,取消掉 if (event_mask != 0) { cancel_wakeup(event_handler, event_mask); } //不检测了,失败了就是命不好 handler_map_.erase(event_handler->get_handle()); // if (call_handle_close) { //调用handle_close event_handler->handle_close(); } return 0; }
//从反应器注销一个ZCE_Event_Handler,同事取消他所有的mask //event_mask其实只判断里面的DONT_CALL int ZCE_Reactor::remove_handler(ZCE_Event_Handler *event_handler, bool call_handle_close) { int ret = 0; ZCE_SOCKET socket_hd = event_handler->get_handle(); ZCE_Event_Handler *tmp_handler = NULL; //remove_handler可能会出现两次调用的情况,我推荐你直接调用handle_close ret = find_event_handler(socket_hd, tmp_handler); if (ret != 0) { // 未找到 return -1; } //不好用这个断言保护,因为可能出现一些重复调用等问题 //ZCE_ASSERT_DGB(tmp_handler == event_handler); int event_mask = event_handler->get_mask(); //如果有mask,取消掉 if (event_mask != 0) { cancel_wakeup(event_handler, event_mask); } //不检测了,失败了就是命不好 handler_map_.erase(event_handler->get_handle()); // if (call_handle_close) { //调用handle_close event_handler->handle_close(); } return 0; }
//进行IO触发操作 int ZCE_WFMO_Reactor::handle_events(ZCE_Time_Value *time_out, size_t *size_event) { int ret = 0; *size_event = 0; DWORD wait_msec = static_cast<DWORD>(time_out->total_msec()); DWORD watch_ary_size = static_cast<DWORD>(handler_map_.size()); DWORD wait_status = WaitForMultipleObjects(watch_ary_size, watch_handle_ary_, FALSE, wait_msec); if (wait_status == WAIT_FAILED) { ZCE_LOG(RS_ERROR, "[%s] ::WaitForMultipleObjects fail,error [%u].", __ZCE_FUNC__, ZCE_LIB::last_error()); return -1; } //如果是超时 if (wait_status == WAIT_TIMEOUT) { errno = ETIMEDOUT; return -1; } *size_event = 1; size_t activate_id = wait_status - WAIT_OBJECT_0; ZCE_Event_Handler *event_hdl = NULL; //因为Socket 的事件处理,放入的反应器的是事件句柄,但在event handle内部是socket句柄,而 //保存event handle的 map是用socket句柄做得key,所以有如下的代码 if (ZCE_INVALID_SOCKET != watch_socket_ary_[activate_id]) { ret = find_event_handler((ZCE_HANDLE)watch_socket_ary_[activate_id], event_hdl); } else { ret = find_event_handler((ZCE_HANDLE)watch_handle_ary_[activate_id], event_hdl); } if (0 != ret) { ZCE_LOG(RS_INFO, "[zcelib] [%s] fail find handle [%lu],maybe one handle is close previous.", __ZCE_FUNC__, watch_socket_ary_[activate_id]); return -1; } int event_mask = event_hdl->get_mask(); if (ZCE_BIT_IS_SET(event_mask, ZCE_Event_Handler::READ_MASK) || ZCE_BIT_IS_SET(event_mask, ZCE_Event_Handler::ACCEPT_MASK) || ZCE_BIT_IS_SET(event_mask, ZCE_Event_Handler::CONNECT_MASK) || ZCE_BIT_IS_SET(event_mask, ZCE_Event_Handler::EXCEPT_MASK) || ZCE_BIT_IS_SET(event_mask, ZCE_Event_Handler::WRITE_MASK)) { WSANETWORKEVENTS socket_event; ::WSAEnumNetworkEvents((SOCKET)watch_socket_ary_[activate_id], watch_handle_ary_[activate_id], &socket_event); SOCKET socket_handle = (SOCKET)watch_socket_ary_[activate_id]; if (ZCE_BIT_IS_SET(socket_event.lNetworkEvents, FD_ACCEPT)) { event_hdl->handle_input(); } if (ZCE_BIT_IS_SET(socket_event.lNetworkEvents, FD_READ)) { //因为很多事件会并列触发,而前面一个事件处理,可能会关闭event_hdl,所以必须double check ret = find_event_handler((ZCE_HANDLE)socket_handle, event_hdl); if (ret == 0) { ret = event_hdl->handle_input(); if (ret == -1) { event_hdl->handle_close(); } } } if (ZCE_BIT_IS_SET(socket_event.lNetworkEvents, FD_CLOSE)) { ret = find_event_handler((ZCE_HANDLE)socket_handle, event_hdl); if (ret == 0) { ret = event_hdl->handle_input(); if (ret == -1) { event_hdl->handle_close(); } } } if (ZCE_BIT_IS_SET(socket_event.lNetworkEvents, FD_WRITE)) { ret = find_event_handler((ZCE_HANDLE)socket_handle, event_hdl); if (ret == 0) { ret = event_hdl->handle_output(); if (ret == -1) { event_hdl->handle_close(); } } } if (ZCE_BIT_IS_SET(socket_event.lNetworkEvents, FD_OOB)) { ret = find_event_handler((ZCE_HANDLE)socket_handle, event_hdl); if (ret == 0) { ret = event_hdl->handle_exception(); if (ret == -1) { event_hdl->handle_close(); } } } if (ZCE_BIT_IS_SET(socket_event.lNetworkEvents, FD_CONNECT)) { ret = find_event_handler((ZCE_HANDLE)socket_handle, event_hdl); if (ret == 0) { //统一,异步CONNECT如果失败,调用handle_input,成功调用handle_output if (socket_event.iErrorCode[FD_CONNECT_BIT]) { ret = event_hdl->handle_input(); } else { ret = event_hdl->handle_output(); } if (ret == -1) { event_hdl->handle_close(); } } } } if (ZCE_BIT_IS_SET(event_mask, ZCE_Event_Handler::INOTIFY_MASK)) { ret = event_hdl->handle_input(); if (ret == -1) { event_hdl->handle_close(); } } return 0; }
void ZCE_Epoll_Reactor::process_ready_event(struct epoll_event *ep_event) { int ret = 0; ZCE_Event_Handler *event_hdl = NULL; bool event_in_happen = false, event_out_happen = false; ret = find_event_handler(ep_event->data.fd, event_hdl); //到这个地方,可能是代码有问题,也可能不是,因为一个事件处理后,可能就被关闭了? if (0 != ret) { return; } //根据不同的事件进行调动,触发 int hdl_ret = 0; //【注意】所有的reactor 都要保证各种触发的顺序,必须保证,否则就有不兼容的问题,正确的顺序应该是读,写,异常处理 //修正connect发生连接错误,内部希望停止处理,但epoll会返回3个事件的修正, //先说明一下这个问题,当内部处理的事件发生错误后,上层可能就会删除掉对应的ZCE_Event_Handler,但底层可能还有事件要触发。 //由于该代码的时候面临抉择,我必须写一段说明,我在改这段代码的时候有几种种方式, //1.整体写成do { break} while()的方式,每个IO事件都作为触发方式,这个好处是简单,但对于epoll,如果是水平触发,那么你可能丢失事件 //2.继续使用return -1作为一个判断,ACE就是这样的,原来曾经觉得ACE这个设计有点冗余,但自己设计看来,还是有好处的, //3.每次调用后,都检查一下event_hdl是否还存在, //最后我采用了兼容2,3的方法,2是为了和ACE兼容,3是为了保证就是你TMD天翻地覆,我也能应付, //代码有点怪,部分目的是加快速度,避免每个调用都要检查, //READ和CONNECT事件都调用handle_input if (ep_event->events & EPOLLIN ) { event_in_happen = true; hdl_ret = event_hdl->handle_input(); //返回-1表示 handle_xxxxx希望调用handle_close退出 if (hdl_ret == -1) { event_hdl->handle_close(); } } //READ和ACCEPT事件都调用handle_input if (ep_event->events & EPOLLOUT ) { //如果写事件触发了,那么里面可能调用handle_close,再查询一次,double check. if (event_in_happen) { ret = find_event_handler(ep_event->data.fd, event_hdl); //到这个地方,可能是代码有问题,也可能不是,因为一个事件处理后,可能就被关闭了? if (0 != ret) { return; } } event_out_happen = true; hdl_ret = event_hdl->handle_output(); //返回-1表示 handle_xxxxx希望调用handle_close退出 if (hdl_ret == -1) { event_hdl->handle_close(); } } //异常事件,其实我也不知道,什么算异常 if (ep_event->events & EPOLLERR ) { //如果读取或者写事件触发了,那么里面可能调用handle_close,再查询一次,double check. if (event_out_happen || event_in_happen) { ret = find_event_handler(ep_event->data.fd, event_hdl); //到这个地方,可能是代码有问题,也可能不是,因为一个事件处理后,可能就被关闭了? if (0 != ret) { return; } } hdl_ret = event_hdl->handle_exception(); //返回-1表示 handle_xxxxx希望调用handle_close退出 if (hdl_ret == -1) { event_hdl->handle_close(); } } }