用ACE的Reactor模式实现网络通讯时,ACE内部用 WSAEventSelect 函数把网络事件与一个事件对象关联起来,目的是为了后面用WaitForMultipleObjects函数统一处理。
下面是ACE 的 ACE_WFMO_Reactor::register_handler_i 函数的代码,里面调用了WSAEventSelect 函数。
- int
- ACE_WFMO_Reactor::register_handler_i (ACE_HANDLE event_handle,ACE_HANDLE io_handle,ACE_Event_Handler *event_handler,ACE_Reactor_Mask new_masks)
- {
- // If this is a Winsock 1 system,the underlying event assignment will
- // not work,so don't try. Winsock 1 must use ACE_Select_Reactor for
- // reacting to socket activity.
- #if !defined (ACE_HAS_WINSOCK2) || (ACE_HAS_WINSOCK2 == 0)
- ACE_UNUSED_ARG (event_handle);
- ACE_UNUSED_ARG (io_handle);
- ACE_UNUSED_ARG (event_handler);
- ACE_UNUSED_ARG (new_masks);
- ACE_NOTSUP_RETURN (-1);
- #else
- // Make sure that the <handle> is valid
- if (io_handle == ACE_INVALID_HANDLE)
- io_handle = event_handler->get_handle ();
- if (this->handler_rep_.invalid_handle (io_handle))
- {
- errno = ERROR_INVALID_HANDLE;
- return -1;
- }
- long new_network_events = 0;
- bool delete_event = false;
- auto_ptr <ACE_Auto_Event> event;
- // Look up the repository to see if the <event_handler> is already
- // there.
- ACE_Reactor_Mask old_masks;
- int found = this->handler_rep_.modify_network_events_i (io_handle,new_masks,old_masks,new_network_events,event_handle,delete_event,ACE_Reactor::ADD_MASK);
- // Check to see if the user passed us a valid event; If not then we
- // need to create one
- if (event_handle == ACE_INVALID_HANDLE)
- {
- // Note: don't change this since some C++ compilers have
- // <auto_ptr>s that don't work properly...
- auto_ptr<ACE_Auto_Event> tmp (new ACE_Auto_Event);
- event = tmp;
- event_handle = event->handle ();
- delete_event = true;
- }
- int result = ::WSAEventSelect ((SOCKET) io_handle,new_network_events);
- // If we had found the <Event_Handler> there is nothing more to do
- if (found)
- return result;
- else if (result != SOCKET_ERROR &&
- this->handler_rep_.bind_i (1,event_handler,io_handle,delete_event) != -1)
- {
- // The <event_handler> was not found in the repository,add to
- // the repository.
- if (delete_event)
- {
- // Clear out the handle in the ACE_Auto_Event so that when
- // it is destroyed,the handle isn't closed out from under
- // the reactor. After setting it,running down the event
- // (via auto_ptr<> event,above) at function return will
- // cause an error because it'll try to close an invalid handle.
- // To avoid that smashing the errno value,save the errno
- // here,explicitly remove the event so the dtor won't do it
- // again,then restore errno.
- ACE_Errno_Guard guard (errno);
- event->handle (ACE_INVALID_HANDLE);
- event->remove ();
- }
- return 0;
- }
- else
- return -1;
- #endif /* ACE_HAS_WINSOCK2 || ACE_HAS_WINSOCK2 == 0 */
- }