RFC: new async_private implementation

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Tue Jan 8 11:14:33 CST 2002


The patch below implements my ideas from the
"struct async_private needs generalization for Winsock"
thread.

It's a patch against CVS 2002-01-08.

The Winsock stuff is still missing, that's the next step.
This is only a trivial recoding of the File IO (compiles, successfully
tested with my async file IO test code), whith the
"generic" fields in async_private and the "fileio-specific" fields
in the rest of the async_fileio structure.

Note: Since it seems agreeable to use the lpOverlapped in Winsock
the same way as for file IO, I made lpOverlapped a "generic" field.

Mike (or other people interested), if you can test this against your
serial port code I'd be grateful.

Martin

Patch file:	async_private.diff
Purpose:	New winsock-friendly async_private implementation
Created:	2002-01-08
Applies:	CVS 2002-01-08

ChangeLog:

wine/include/file.h:
        struct async_private:
                - remove buffer, count, completion_func fields.
                - add call_completion field (callback function
                that calls the completion function).
        struct async_fileio:
                - "Derived" from async_private, contains.
                remove buffer, count, completion_func fields.

wine/scheduler/synchro.c:
        call_completion_routine(): function removed.
        finish_async(): use ovp->completion_func instead of
                call_completion_routine.
        check_async_list(): Initialize ovp.

wine/files/file.c:
        fileio_call_completion_func(): New function, FileIO-specific callback.
        FILE_AsyncReadService():
                - use struct async_fileio for specific fields.
        FILE_AsyncWriteService():
                - dito.
        FILE_ReadFileEx():
                - use async_fileio struct for overlapped initialization.
                - initialize ovp->call_completion field.
        FILE_WriteFileEx():
                - dito.

dlls/kernel/comm.c:
        COMM_WaitCommEventService():
                - use struct async_fileio for "buffer" field.
        COMM_WaitCommEvent():
                - see FILE_ReadFileEx().

Martin Wilck <Martin.Wilck at Fujitsu-Siemens.com>

diff -ruX diffignore CVS/wine/dlls/kernel/comm.c MW/wine/dlls/kernel/comm.c
--- CVS/wine/dlls/kernel/comm.c	Tue Jan  8 17:43:25 2002
+++ MW/wine/dlls/kernel/comm.c	Tue Jan  8 17:47:41 2002
@@ -1515,11 +1515,12 @@
 static void COMM_WaitCommEventService(async_private *ovp)
 {
     LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
+    async_fileio *fileio = (async_fileio*) ovp;

     TRACE("overlapped %p\n",lpOverlapped);

     /* FIXME: detect other events */
-            *ovp->buffer = EV_RXCHAR;
+            *fileio->buffer = EV_RXCHAR;

     lpOverlapped->Internal = STATUS_SUCCESS;
 }
@@ -1536,7 +1537,7 @@
     LPOVERLAPPED lpOverlapped) /* [in/out] for Asynchronous waiting */
 {
     int fd,ret;
-    async_private *ovp;
+    async_fileio *ovp;

     if(!lpOverlapped)
     {
@@ -1556,26 +1557,27 @@
     if(fd<0)
 	return FALSE;

-    ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+    ovp = (async_fileio *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
     if(!ovp)
     {
         close(fd);
         return FALSE;
     }
-    ovp->lpOverlapped = lpOverlapped;
-    ovp->func = COMM_WaitCommEventService;
+    ovp->async.handle = hFile;
+    ovp->async.fd = fd;
+    ovp->async.type = ASYNC_TYPE_WAIT;
+    ovp->async.lpOverlapped = lpOverlapped;
+    ovp->async.func = COMM_WaitCommEventService;
+    ovp->async.call_completion = NULL;
     ovp->buffer = (char *)lpdwEvents;
-    ovp->fd = fd;
     ovp->count = 0;
     ovp->completion_func = 0;
-    ovp->type = ASYNC_TYPE_WAIT;
-    ovp->handle = hFile;

-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if(ovp->next)
-        ovp->next->prev=ovp;
-    NtCurrentTeb()->pending_list = ovp;
+    ovp->async.next = NtCurrentTeb()->pending_list;
+    ovp->async.prev = NULL;
+    if(ovp->async.next)
+        ovp->async.next->prev=&ovp->async;
+    NtCurrentTeb()->pending_list = &ovp->async;

     /* start an ASYNCHRONOUS WaitCommEvent */
     SERVER_START_REQ( register_async )
diff -ruX diffignore CVS/wine/files/file.c MW/wine/files/file.c
--- CVS/wine/files/file.c	Tue Jan  8 17:43:51 2002
+++ MW/wine/files/file.c	Tue Jan  8 17:47:41 2002
@@ -1298,6 +1298,21 @@
 }

 /***********************************************************************
+ *            fileio_call_completion_func (INTERNAL)
+ */
+void CALLBACK fileio_call_completion_func (ULONG_PTR data)
+{
+    async_fileio *ovp = (async_fileio*) data;
+    TRACE ("data: %p\n", ovp);
+
+    ovp->completion_func(ovp->async.lpOverlapped->Internal,
+                         ovp->async.lpOverlapped->InternalHigh,
+                         ovp->async.lpOverlapped);
+    ovp->completion_func=NULL;
+    HeapFree(GetProcessHeap(), 0, ovp);
+}
+
+/***********************************************************************
  *             FILE_AsyncReadService      (INTERNAL)
  *
  *  This function is called while the client is waiting on the
@@ -1305,18 +1320,19 @@
  */
 static void FILE_AsyncReadService(async_private *ovp)
 {
+    async_fileio *fileio = (async_fileio*) ovp;
     LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
     int result, r;
     int already = lpOverlapped->InternalHigh;

-    TRACE("%p %p\n", lpOverlapped, ovp->buffer );
+    TRACE("%p %p\n", lpOverlapped, fileio->buffer );

     /* check to see if the data is ready (non-blocking) */

-    result = pread (ovp->fd, &ovp->buffer[already], ovp->count - already,
+    result = pread (ovp->fd, &fileio->buffer[already], fileio->count - already,
                     OVERLAPPED_OFFSET (lpOverlapped) + already);
     if ((result < 0) && (errno == ESPIPE))
-        result = read (ovp->fd, &ovp->buffer[already], ovp->count - already);
+        result = read (ovp->fd, &fileio->buffer[already], fileio->count - already);

     if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
     {
@@ -1336,7 +1352,7 @@
     lpOverlapped->InternalHigh += result;
     TRACE("read %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);

-    if(lpOverlapped->InternalHigh < ovp->count)
+    if(lpOverlapped->InternalHigh < fileio->count)
         r = STATUS_PENDING;
     else
         r = STATUS_SUCCESS;
@@ -1352,7 +1368,7 @@
 			 LPOVERLAPPED overlapped,
 			 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
-    async_private *ovp;
+    async_fileio *ovp;
     int fd;

     TRACE("file %d to buf %p num %ld %p func %p\n",
@@ -1372,7 +1388,7 @@
         return FALSE;
     }

-    ovp = (async_private *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+    ovp = (async_fileio *) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
     if(!ovp)
     {
         TRACE("HeapAlloc Failed\n");
@@ -1380,21 +1396,23 @@
         close(fd);
         return FALSE;
     }
-    ovp->lpOverlapped = overlapped;
-    ovp->count = bytesToRead;
+
+    ovp->async.handle = hFile;
+    ovp->async.fd = fd;
+    ovp->async.type = ASYNC_TYPE_READ;
+    ovp->async.lpOverlapped = overlapped;
+    ovp->async.func = FILE_AsyncReadService;
+    ovp->async.call_completion = (lpCompletionRoutine ? fileio_call_completion_func : NULL);
     ovp->completion_func = lpCompletionRoutine;
-    ovp->func = FILE_AsyncReadService;
     ovp->buffer = buffer;
-    ovp->fd = fd;
-    ovp->type = ASYNC_TYPE_READ;
-    ovp->handle = hFile;
+    ovp->count = bytesToRead;

     /* hook this overlap into the pending async operation list */
-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if(ovp->next)
-        ovp->next->prev = ovp;
-    NtCurrentTeb()->pending_list = ovp;
+    ovp->async.next = NtCurrentTeb()->pending_list;
+    ovp->async.prev = NULL;
+    if(ovp->async.next)
+        ovp->async.next->prev = &ovp->async;
+    NtCurrentTeb()->pending_list = &ovp->async;

     if ( !FILE_StartAsync(hFile, overlapped, ASYNC_TYPE_READ, bytesToRead, STATUS_PENDING) )
     {
@@ -1550,18 +1568,19 @@
  */
 static void FILE_AsyncWriteService(struct async_private *ovp)
 {
+    async_fileio *fileio = (async_fileio *) ovp;
     LPOVERLAPPED lpOverlapped = ovp->lpOverlapped;
     int result, r;
     int already = lpOverlapped->InternalHigh;

-    TRACE("(%p %p)\n",lpOverlapped,ovp->buffer);
+    TRACE("(%p %p)\n",lpOverlapped,fileio->buffer);

     /* write some data (non-blocking) */

-    result = pwrite(ovp->fd, &ovp->buffer[already], ovp->count - already,
+    result = pwrite(ovp->fd, &fileio->buffer[already], fileio->count - already,
                     OVERLAPPED_OFFSET (lpOverlapped) + already);
     if ((result < 0) && (errno == ESPIPE))
-        result = write(ovp->fd, &ovp->buffer[already], ovp->count - already);
+        result = write(ovp->fd, &fileio->buffer[already], fileio->count - already);

     if ( (result<0) && ((errno == EAGAIN) || (errno == EINTR)))
     {
@@ -1578,9 +1597,9 @@

     lpOverlapped->InternalHigh += result;

-    TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,ovp->count);
+    TRACE("wrote %d more bytes %ld/%d so far\n",result,lpOverlapped->InternalHigh,fileio->count);

-    if(lpOverlapped->InternalHigh < ovp->count)
+    if(lpOverlapped->InternalHigh < fileio->count)
         r = STATUS_PENDING;
     else
         r = STATUS_SUCCESS;
@@ -1596,7 +1615,7 @@
 			 LPOVERLAPPED overlapped,
 			 LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)
 {
-    async_private *ovp;
+    async_fileio *ovp;

     TRACE("file %d to buf %p num %ld %p func %p stub\n",
 	  hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine);
@@ -1616,34 +1635,35 @@
         return FALSE;
     }

-    ovp = (async_private*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_private));
+    ovp = (async_fileio*) HeapAlloc(GetProcessHeap(), 0, sizeof (async_fileio));
     if(!ovp)
     {
         TRACE("HeapAlloc Failed\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
         return FALSE;
     }
-    ovp->lpOverlapped = overlapped;
-    ovp->func = FILE_AsyncWriteService;
+    ovp->async.handle = hFile;
+    ovp->async.fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+    ovp->async.type = ASYNC_TYPE_WRITE;
+    ovp->async.lpOverlapped = overlapped;
+    ovp->async.func = FILE_AsyncWriteService;
+    ovp->async.call_completion = (lpCompletionRoutine ? fileio_call_completion_func : NULL);
     ovp->buffer = (LPVOID) buffer;
     ovp->count = bytesToWrite;
     ovp->completion_func = lpCompletionRoutine;
-    ovp->fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
-    ovp->type = ASYNC_TYPE_WRITE;
-    ovp->handle = hFile;

-    if(ovp->fd <0)
+    if(ovp->async.fd <0)
     {
         HeapFree(GetProcessHeap(), 0, ovp);
         return FALSE;
     }

     /* hook this overlap into the pending async operation list */
-    ovp->next = NtCurrentTeb()->pending_list;
-    ovp->prev = NULL;
-    if(ovp->next)
-        ovp->next->prev = ovp;
-    NtCurrentTeb()->pending_list = ovp;
+    ovp->async.next = NtCurrentTeb()->pending_list;
+    ovp->async.prev = NULL;
+    if(ovp->async.next)
+        ovp->async.next->prev = &ovp->async;
+    NtCurrentTeb()->pending_list = &ovp->async;

     return TRUE;
 }
diff -ruX diffignore CVS/wine/include/file.h MW/wine/include/file.h
--- CVS/wine/include/file.h	Tue Jan  8 17:43:45 2002
+++ MW/wine/include/file.h	Tue Jan  8 17:47:41 2002
@@ -33,20 +33,31 @@

 /* overlapped private structure */
 struct async_private;
-typedef void (*async_handler)(struct async_private *ovp);
+
+typedef void (*async_handler) (struct async_private *ovp);
+typedef void CALLBACK (*async_call_completion_func) (ULONG_PTR data);
+
+extern void CALLBACK fileio_call_completion_func (ULONG_PTR data);
+
 typedef struct async_private
 {
-     LPOVERLAPPED  lpOverlapped;
-     HANDLE        handle;
-     int           fd;
-     char         *buffer;
-     async_handler func;
-     int           count;
-     int           type;
-     LPOVERLAPPED_COMPLETION_ROUTINE completion_func;
-     struct async_private *next;
-     struct async_private *prev;
+    HANDLE                           handle;
+    int                              fd;
+    int                              type;
+    LPOVERLAPPED                     lpOverlapped;
+    async_handler                    func;
+    async_call_completion_func       call_completion;
+    struct async_private             *next;
+    struct async_private             *prev;
 } async_private;
+
+typedef struct async_fileio
+{
+    async_private                    async;
+    LPOVERLAPPED_COMPLETION_ROUTINE  completion_func;
+    char                             *buffer;
+    int                              count;
+} async_fileio;

 extern void WINAPI check_async_list(LPOVERLAPPED ov, DWORD status);
 extern void finish_async(struct async_private *ovp, DWORD status);
diff -ruX diffignore CVS/wine/scheduler/synchro.c MW/wine/scheduler/synchro.c
--- CVS/wine/scheduler/synchro.c	Tue Jan  8 17:43:37 2002
+++ MW/wine/scheduler/synchro.c	Tue Jan  8 17:47:41 2002
@@ -36,25 +36,14 @@
     }
 }

-static void CALLBACK call_completion_routine(ULONG_PTR data)
-{
-    async_private* ovp = (async_private*)data;
-
-    ovp->completion_func(ovp->lpOverlapped->Internal,
-                         ovp->lpOverlapped->InternalHigh,
-                         ovp->lpOverlapped);
-    ovp->completion_func=NULL;
-    HeapFree(GetProcessHeap(), 0, ovp);
-}
-
 void finish_async(async_private *ovp, DWORD status)
 {
     ovp->lpOverlapped->Internal=status;

-    /* call ReadFileEx/WriteFileEx's overlapped completion function */
-    if(ovp->completion_func)
+    /* call overlapped completion function */
+    if(ovp->call_completion)
     {
-        QueueUserAPC(call_completion_routine,GetCurrentThread(),(ULONG_PTR)ovp);
+        QueueUserAPC(ovp->call_completion,GetCurrentThread(),(ULONG_PTR)ovp);
     }

     /* remove it from the active list */
@@ -70,7 +59,7 @@
     ovp->prev=NULL;

     close(ovp->fd);
-    if(!ovp->completion_func) HeapFree(GetProcessHeap(), 0, ovp);
+    if(!ovp->call_completion) HeapFree(GetProcessHeap(), 0, ovp);
 }

 /***********************************************************************
@@ -80,7 +69,7 @@
  */
 void WINAPI check_async_list(LPOVERLAPPED overlapped, DWORD status)
 {
-    async_private *ovp;
+    async_private *ovp = NULL;

     /* fprintf(stderr,"overlapped %p status %x\n",overlapped,status); */






More information about the wine-devel mailing list