用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,
event_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,
new_network_events,
io_handle,
event_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 */
}