struct async_private needs generalization for Winsock

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Mon Jan 7 11:07:17 CST 2002


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:Martin.Wilck at Fujitsu-Siemens.com
D-33106 Paderborn           http://www.fujitsu-siemens.com/primergy









More information about the wine-devel mailing list