<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=Content-Type content="text/html; charset=GB2312">
<META content="MSHTML 6.00.2900.3314" name=GENERATOR>
<STYLE>BLOCKQUOTE {
        MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px; MARGIN-LEFT: 2em
}
OL {
        MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
UL {
        MARGIN-TOP: 0px; MARGIN-BOTTOM: 0px
}
</STYLE>
</HEAD>
<BODY 
style="BORDER-TOP-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px">
<DIV><FONT face=Verdana><FONT size=2>Integrate Windows I/O Completion Port into 
Libevent</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>IOCP is true async i/o model, and libevent 
is event-driven i/o model.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>1. How to emulate event-driven recv/send 
?<BR>It is possible to use IOCP to emulate event-driven mode. When you make read 
or write calls, pass in a zero-byte buffer (ie, you can manage your i/o buffers 
using event driven semantics). So if you issue a read passing in a zero-byte 
length buffer, your will get notified when there is data to 
read.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>2. How to emulate event-driven accept 
?<BR>The WSAEventSelect API provides an event-driven accept 
mechanism.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>3. How to integrate these two mechanism 
?<BR>When we issue a WSARecv or WSASend, we need to pass a OVERLAPPED structure. 
This structure has a hEvent member.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2><A 
href="http://msdn.microsoft.com/en-us/library/ms742203(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms742203(VS.85).aspx</A><BR>If 
the lpCompletionRoutine parameter is NULL, the hEvent parameter of lpOverlapped 
is signaled when the overlapped operation completes if it contains a valid event 
object handle. An application can use WSAWaitForMultipleEvents or 
WSAGetOverlappedResult to wait or poll on the event object.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>We could use one event for all 
WSARecv/WSASend.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2><A 
href="http://msdn.microsoft.com/en-us/library/ms686211(VS.85).aspx">http://msdn.microsoft.com/en-us/library/ms686211(VS.85).aspx</A><BR>Setting 
an event that is already set has no effect.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>So it is possible to use 
WSAWaitForMultipleEvents to integrate IOCP and 
WSAEventSelect.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>4. Solution</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>/* objects[0] for iocp operations, 
object[1..63] for accept */<BR>HANDLE objects[64];<BR>struct event * 
accepts[64];</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>struct win32iocp_event 
event1;<BR>event1.overlapped.hEvent = objects[0];<BR>WSARecv( ..., 
&amp;event1.overlapped, ... );<BR>....</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>struct win32iocp_event 
event2;<BR>event2.overlapped.hEvent = objects[0];<BR>WSASend( ..., 
&amp;event2.overlapped, ... );<BR>...</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>WSAEventSelect( ev1-&gt;ev_fd, objects[1], 
FD_ACCEPT );<BR>accepts[1] = ev1;<BR>...</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>WSAEventSelect( ev2-&gt;ev_fd, objects[2], 
FD_ACCEPT );<BR>accepts[2] = ev2;<BR>...</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>int index = WSAWaitForMultipleEvents( 64, 
objects, FALSE, timeout, FALSE );<BR>index = index - 
WSA_WAIT_EVENT_0;</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>if( index &gt; 0 ) {<BR>&nbsp;struct event 
* event = win32iocp_op-&gt;accepts[index];<BR>&nbsp;event_active (event, EV_READ 
| EV_ACCEPT, 1);<BR>}</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>if( index == 0 ) {<BR>&nbsp;for( ; ; ) 
{<BR>&nbsp;&nbsp;GetQueuedCompletionPort( ...... 
);<BR>&nbsp;}<BR>}</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2>5. Limitation<BR>It can only support 63 
accept fds.</FONT></FONT></DIV>
<DIV>&nbsp;</DIV>
<DIV>6. Source code</DIV>
<DIV><A 
href="http://spserver.googlecode.com/files/libevent-1.4.4-iocp.zip">http://spserver.googlecode.com/files/libevent-1.4.4-iocp.zip</A></DIV>
<DIV>diff file : libevent-1.4.4-iocp\libevent-iocp\diff.txt</DIV>
<DIV>add file : libevent-1.4.4-iocp\WIN32-Code\win32iocp.cpp</DIV>
<DIV>&nbsp;</DIV>
<DIV><FONT face=Verdana><FONT size=2></FONT>&nbsp;</DIV>
<DIV><FONT size=2></FONT>&nbsp;</DIV>
<DIV align=left><FONT size=2>
<HR style="WIDTH: 122px; HEIGHT: 2px" SIZE=2>
</FONT></DIV>
<DIV><FONT color=#c0c0c0><FONT size=2><SPAN>liusifan</SPAN></FONT></DIV>
<DIV><FONT size=2>2008-06-01</FONT></FONT></DIV></FONT></BODY></HTML>