示例#1
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_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;
}
示例#3
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;
}
示例#6
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();
        }
    }
}