Patch: async-file.diff (4 in series)

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Fri Apr 12 10:19:59 CDT 2002


Patch: async-file.diff

Some improvements to the async IO API.

- Need a "cleanup" method.

- calling the "call_completion" method unconditionally in finish_async
  (introduced by me) was wrong, because the thread may never be in an
  alertable wait state -> call it only if user completion function is present.

- We need two constant "ops" objects, one with and one without call_completion
  method (the event field may NOT be used to determine whether the completion
  must be called or not).

- STATUS_CANCELLED is correct for cancelled requests
  ( corresponds to ERROR_OPERATION_ABORTED ).

Modified files:

        dlls/kernel:    comm.c
        files:          file.c
        include:        async.h
        server:         async.c

diff -ruNX ignore TMP/wine/dlls/kernel/comm.c MW/wine/dlls/kernel/comm.c
--- TMP/wine/dlls/kernel/comm.c	Fri Apr 12 11:47:48 2002
+++ MW/wine/dlls/kernel/comm.c	Fri Apr 12 12:27:07 2002
@@ -99,14 +99,15 @@
 static DWORD commio_get_async_status (const async_private *ovp);
 static DWORD commio_get_async_count (const async_private *ovp);
 static void commio_set_async_status (async_private *ovp, const DWORD status);
-static void CALLBACK commio_call_completion_func (ULONG_PTR data);
+static void commio_async_cleanup  (async_private *ovp);

 static async_ops commio_async_ops =
 {
     commio_get_async_status,       /* get_status */
     commio_set_async_status,       /* set_status */
     commio_get_async_count,        /* get_count */
-    commio_call_completion_func    /* call_completion */
+    NULL,                          /* call_completion */
+    commio_async_cleanup           /* cleanup */
 };

 typedef struct async_commio
@@ -131,9 +132,9 @@
     return 0;
 }

-static void CALLBACK commio_call_completion_func (ULONG_PTR data)
+static void commio_async_cleanup  (async_private *ovp)
 {
-    HeapFree(GetProcessHeap(), 0, (void*) data);
+    HeapFree(GetProcessHeap(), 0, ovp );
 }

 /***********************************************************************/
diff -ruNX ignore TMP/wine/files/file.c MW/wine/files/file.c
--- TMP/wine/files/file.c	Fri Apr 12 11:59:51 2002
+++ MW/wine/files/file.c	Fri Apr 12 12:28:22 2002
@@ -88,13 +88,24 @@
 static DWORD fileio_get_async_count (const async_private *ovp);
 static void fileio_set_async_status (async_private *ovp, const DWORD status);
 static void CALLBACK fileio_call_completion_func (ULONG_PTR data);
+static void fileio_async_cleanup (async_private *ovp);

 static async_ops fileio_async_ops =
 {
     fileio_get_async_status,       /* get_status */
     fileio_set_async_status,       /* set_status */
     fileio_get_async_count,        /* get_count */
-    fileio_call_completion_func    /* call_completion */
+    fileio_call_completion_func,   /* call_completion */
+    fileio_async_cleanup           /* cleanup */
+};
+
+static async_ops fileio_nocomp_async_ops =
+{
+    fileio_get_async_status,       /* get_status */
+    fileio_set_async_status,       /* set_status */
+    fileio_get_async_count,        /* get_count */
+    NULL,                          /* call_completion */
+    fileio_async_cleanup           /* cleanup */
 };

 typedef struct async_fileio
@@ -128,12 +139,16 @@
     async_fileio *ovp = (async_fileio*) data;
     TRACE ("data: %p\n", ovp);

-    if (ovp->completion_func)
-        ovp->completion_func(ovp->lpOverlapped->Internal,
-                             ovp->lpOverlapped->InternalHigh,
-                             ovp->lpOverlapped);
+    ovp->completion_func( ovp->lpOverlapped->Internal,
+                          ovp->lpOverlapped->InternalHigh,
+                          ovp->lpOverlapped );
+
+    fileio_async_cleanup ( &ovp->async );
+}

-    HeapFree(GetProcessHeap(), 0, ovp);
+static void fileio_async_cleanup ( struct async_private *ovp )
+{
+    HeapFree ( GetProcessHeap(), 0, ovp );
 }

 /***********************************************************************
@@ -1479,6 +1494,8 @@
 {
     async_fileio *ovp;
     int fd;
+    int flags;
+    enum fd_type type;

     TRACE("file %d to buf %p num %ld %p func %p\n",
 	  hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine);
@@ -1490,10 +1507,11 @@
         return FALSE;
     }

-    fd = FILE_GetUnixHandle( hFile, GENERIC_READ );
-    if(fd<0)
+    fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags);
+    if ( fd < 0 )
     {
-        TRACE("Couldn't get FD\n");
+        WARN ( "Couldn't get FD\n" );
+        SetLastError ( ERROR_INVALID_PARAMETER );
         return FALSE;
     }

@@ -1502,11 +1520,10 @@
     {
         TRACE("HeapAlloc Failed\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        close(fd);
-        return FALSE;
+        goto error;
     }

-    ovp->async.ops = &fileio_async_ops;
+    ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops );
     ovp->async.handle = hFile;
     ovp->async.fd = fd;
     ovp->async.type = ASYNC_TYPE_READ;
@@ -1518,6 +1535,11 @@
     ovp->buffer = buffer;

     return !register_new_async (&ovp->async);
+
+error:
+    close (fd);
+    return FALSE;
+
 }

 /***********************************************************************
@@ -1691,6 +1713,8 @@
 {
     async_fileio *ovp;
     int fd;
+    int flags;
+    enum fd_type type;

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

-    fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE );
+    fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags );
     if ( fd < 0 )
     {
         TRACE( "Couldn't get FD\n" );
@@ -1713,8 +1737,7 @@
     {
         TRACE("HeapAlloc Failed\n");
         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-        close (fd);
-        return FALSE;
+        goto error;
     }

     ovp->async.ops = &fileio_async_ops;
@@ -1729,6 +1752,10 @@
     ovp->completion_func = lpCompletionRoutine;

     return !register_new_async (&ovp->async);
+
+error:
+    close (fd);
+    return FALSE;
 }

 /***********************************************************************
diff -ruNX ignore TMP/wine/include/async.h MW/wine/include/async.h
--- TMP/wine/include/async.h	Fri Apr 12 11:47:48 2002
+++ MW/wine/include/async.h	Fri Apr 12 12:25:30 2002
@@ -35,6 +35,7 @@
 typedef DWORD (*async_get_status)(const struct async_private *ovp);
 typedef DWORD (*async_get_count)(const struct async_private *ovp);
 typedef void (*async_set_status)(struct async_private *ovp, const DWORD status);
+typedef void (*async_cleanup)(struct async_private *ovp);

 typedef struct async_ops
 {
@@ -42,6 +43,7 @@
     async_set_status            set_status;
     async_get_count             get_count;
     async_call_completion_func  call_completion;
+    async_cleanup               cleanup;
 } async_ops;

 typedef struct async_private
@@ -74,7 +76,10 @@
     if( ovp->event != INVALID_HANDLE_VALUE )
         NtSetEvent( ovp->event, NULL );

-    QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
+    if ( ovp->ops->call_completion )
+        QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp );
+    else
+        ovp->ops->cleanup ( ovp );
 }

 inline static BOOL __register_async( async_private *ovp, const DWORD status )
@@ -92,7 +97,11 @@
     }
     SERVER_END_REQ;

-    if ( ret ) ovp->ops->set_status ( ovp, GetLastError() );
+    if ( ret ) {
+        SetLastError( RtlNtStatusToDosError(ret) );
+        ovp->ops->set_status ( ovp, ret );
+    }
+
     if ( ovp->ops->get_status (ovp) != STATUS_PENDING )
         finish_async (ovp);

diff -ruNX ignore TMP/wine/server/async.c MW/wine/server/async.c
--- TMP/wine/server/async.c	Fri Apr 12 11:47:48 2002
+++ MW/wine/server/async.c	Fri Apr 12 12:23:56 2002
@@ -71,7 +71,7 @@
 {
     while(q->head)
     {
-        async_notify(q->head, STATUS_HANDLES_CLOSED);
+        async_notify(q->head, STATUS_CANCELLED);
         destroy_async(q->head);
     }
 }






More information about the wine-devel mailing list