Hi Mike, all,
as I pointed out before, we must change the async_private type such that it accomodates the different needs of normal (e.g. ReadFileEx()) and Winsock (e.g. WSARecv()) async requests. The "generic" functions in scheduler/synchro.c must be able to handle these structures without knowing what type of async_private structure they have been passed. I try to summarize the differences between the two request types here: 1. Winsock async requests have a WSAOVERLAPPED struct rather than OVERLAPPED. Unlike File I/O, the routines complete if any positive number of bytes is read (there's no such thing as BytesToRead). 2. Unlike File I/O, The WSAOVERLAPPED struct is *not* accessed in any way, except for the hEvent field. The other fields do not carry useful information and are, according to the Winsock2 specs, reserved to service providers, i.e. we are not allowed to write to them. 3. Winsock functions take a scatter/gather array of type WSABUF* instead of a single buffer, and a number of WSABUFs instead of the number of bytes to read. 4. The completion routine takes an additional DWORD argument. 5. In the case of WSARecvFrom()/WSASendTo(), the socket address and length parameters passed by the user must be stored and filled in at completion. [These are the differences I've come across so far, there may be more.] I'd therefore recommend the following, similar to the treatment of "struct object" and derived types in the server code: struct async_private; typedef void (*async_handler)(struct async_private *ovp); struct async_private { unsigned int type; /* file/socket, read/write/... */ HANDLE handle; int fd; struct async_private *prev; struct async_private *next; async_handler func; } struct async_fileio { struct async_private async; char *buffer; int count; LPOVERLAPPED lpOverlapped; LPOVERLAPPED_COMPLETION_ROUTINE completion_func; } struct async_winsock { struct async_private async; LPWSABUF wsabuf; int n_wsabufs; LPWSAOVERLAPPED overlapped; LPWSAOVERLAPPED_COMPLETION_ROUTINE completion_func; struct WS_sockaddr* addr; /* User-specified pointers */ int *addrlen; int flags; /* Return values */ int NumberOfBytesRead; int status; /* cannot be stored in overlapped */ } To my knowledge, there are only these two types of Asynchronous requests. Thus, using a "struct async_ops" like "struct object_ops" in the server code would probably be too much; the type field could instead be used for distinction between the two request types and the "generic" code in scheduler/synchro.c could incorporate respective case distinctions. To my experience this runs faster than code with function pointers if we have only two cases. Actually, we might even do without the "async_handler" field and decide which function to call only according to the "type" field, but that's a cosmetic issue. Unless anybody objects, I'll soon submit a patch incorporating this approach. Comments welcome, Martin -- Martin Wilck Phone: +49 5251 8 15113 Fujitsu Siemens Computers Fax: +49 5251 8 20409 Heinz-Nixdorf-Ring 1 mailto:[EMAIL PROTECTED] D-33106 Paderborn http://www.fujitsu-siemens.com/primergy