queue-async.diff (2 in series)

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Tue Apr 23 13:07:30 CDT 2002


Patch: queue-async.diff

Add more flexibility to the queue_async server call
by moving most functionality into the object's queue_async method

Patch against: CVS 2002/04/23.

Rationale: The queue_async method in CVS is overloaded (called twice
           with different purpose) and doesn't have full freedom e.g.
           for changing it's status in the event loop.

           This patch makes the request handler for queue_async basically
           a trivial function and puts all work into the object's queue_async
           method.
           => queue_async method gets more flexibility and is not
              overloaded anymore.

Modified files:
        server: async.c  (queue_async handler now trivial)
                object.h (change queue_async method prototype)
                file.c   (implement new queue_async method)
                serial.c (dito).

diff -ruNX ignore CVS/wine/server/async.c TMP/wine/server/async.c
--- CVS/wine/server/async.c	Tue Apr 16 11:16:04 2002
+++ TMP/wine/server/async.c	Mon Apr 22 10:54:15 2002
@@ -150,42 +150,32 @@

 DECL_HANDLER(register_async)
 {
-    struct object *obj;
+    struct object *obj = get_handle_obj( current->process, req->handle, 0, NULL);

-    if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL)) )
-        return;
-
-    if(obj->ops->queue_async)
+    if ( !(obj) || !obj->ops->queue_async )
     {
-        struct async_queue *q = obj->ops->queue_async(obj, NULL, req->type, 0);
-        struct async *async;
-
-        async = find_async(q, current, req->overlapped);
-        if(req->status==STATUS_PENDING)
-        {
-            if(!async)
-                async = create_async(obj, current, req->overlapped);
-
-            if(async)
-            {
-                async->status = req->status;
-                if(!obj->ops->queue_async(obj, async, req->type, req->count))
-                    destroy_async(async);
-            }
-        }
-        else
-        {
-            if(async)
-                destroy_async(async);
-            else
-                set_error(STATUS_INVALID_PARAMETER);
-        }
-
-        set_select_events(obj,obj->ops->get_poll_events(obj));
-    }
-    else
         set_error(STATUS_INVALID_HANDLE);
+        return;
+    }
+
+/*
+ * The queue_async method must do the following:
+ *
+ * 1. Get the async_queue for the request of given type.
+ * 2. Call find_async() to look for the specific client request in the queue (=> NULL if not found).
+ * 3. If status is STATUS_PENDING:
+ *      a) If no async request found in step 2 (new request): call create_async() to initialize one.
+ *      b) Set request's status to STATUS_PENDING.
+ *      c) If the "queue" field of the async request is NULL: call async_insert() to put it into the queue.
+ *    Otherwise:
+ *      If the async request was found in step 2, destroy it by calling destroy_async().
+ * 4. Carry out any operations necessary to adjust the object's poll events
+ *    Usually: set_elect_events (obj, obj->ops->get_poll_events()).
+ *
+ * See also the implementations in file.c, serial.c, and sock.c.
+*/

+    obj->ops->queue_async (obj, req->overlapped, req->status, req->type, req->count);
     release_object(obj);
 }

diff -ruNX ignore CVS/wine/server/file.c TMP/wine/server/file.c
--- CVS/wine/server/file.c	Tue Apr  2 15:39:41 2002
+++ TMP/wine/server/file.c	Mon Apr 22 10:54:15 2002
@@ -69,7 +69,7 @@
 static int file_flush( struct object *obj );
 static int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static void file_destroy( struct object *obj );
-static struct async_queue * file_queue_async(struct object *obj, struct async* async, int type, int count);
+static void file_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count);

 static const struct object_ops file_ops =
 {
@@ -358,9 +358,10 @@
     return FD_TYPE_DEFAULT;
 }

-static struct async_queue *file_queue_async(struct object *obj, struct async *async, int type, int count)
+static void file_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)
 {
     struct file *file = (struct file *)obj;
+    struct async *async;
     struct async_queue *q;

     assert( obj->ops == &file_ops );
@@ -368,7 +369,7 @@
     if ( !(file->flags & FILE_FLAG_OVERLAPPED) )
     {
         set_error ( STATUS_INVALID_HANDLE );
-        return NULL;
+        return;
     }

     switch(type)
@@ -381,13 +382,26 @@
         break;
     default:
         set_error( STATUS_INVALID_PARAMETER );
-        return NULL;
+        return;
     }

-    if(async && !async->q)
-        async_insert(q, async);
+    async = find_async ( q, current, ptr );
+
+    if ( status == STATUS_PENDING )
+    {
+        if ( !async )
+            async = create_async ( obj, current, ptr );
+        if ( !async )
+            return;
+
+        async->status = STATUS_PENDING;
+        if ( !async->q )
+            async_insert( q, async );
+    }
+    else if ( async ) destroy_async ( async );
+    else set_error ( STATUS_INVALID_PARAMETER );

-    return q;
+    set_select_events ( obj, file_get_poll_events ( obj ));
 }

 static void file_destroy( struct object *obj )
diff -ruNX ignore CVS/wine/server/object.h TMP/wine/server/object.h
--- CVS/wine/server/object.h	Thu Apr  4 09:17:15 2002
+++ TMP/wine/server/object.h	Mon Apr 22 10:54:15 2002
@@ -63,8 +63,8 @@
     int  (*flush)(struct object *);
     /* get file information */
     int  (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags);
-    /* queue an async operation */
-    struct async_queue* (*queue_async)(struct object *, struct async *async, int type, int count);
+    /* queue an async operation - see register_async handler in async.c*/
+    void (*queue_async)(struct object *, void* ptr, unsigned int status, int type, int count);
     /* destroy on refcount == 0 */
     void (*destroy)(struct object *);
 };
diff -ruNX ignore CVS/wine/server/serial.c TMP/wine/server/serial.c
--- CVS/wine/server/serial.c	Tue Apr  2 15:39:41 2002
+++ TMP/wine/server/serial.c	Mon Apr 22 10:54:15 2002
@@ -51,7 +51,7 @@
 static int serial_get_fd( struct object *obj );
 static int serial_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
 static int serial_get_poll_events( struct object *obj );
-static struct async_queue * serial_queue_async(struct object *obj, struct async* async, int type, int count);
+static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count);
 static void destroy_serial(struct object *obj);
 static void serial_poll_event( struct object *obj, int event );

@@ -250,24 +250,11 @@
     set_select_events(obj,obj->ops->get_poll_events(obj));
 }

-/*
- * This function is an abuse of overloading that deserves some explanation.
- *
- * It has three purposes:
- *
- * 1. get the queue for a type of async operation
- * 2. requeue an async operation
- * 3. queue a new async operation
- *
- * It is overloaded so that these three functions only take one function pointer
- *  in the object operations list.
- *
- * In all cases, it returns the async queue.
- */
-static struct async_queue *serial_queue_async(struct object *obj, struct async *async, int type, int count)
+static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)
 {
     struct serial *serial = (struct serial *)obj;
     struct async_queue *q;
+    struct async *async;
     int timeout;

     assert(obj->ops == &serial_ops);
@@ -288,19 +275,29 @@
         break;
     default:
         set_error(STATUS_INVALID_PARAMETER);
-        return NULL;
+        return;
     }

-    if(async)
+    async = find_async ( q, current, ptr );
+
+    if ( status == STATUS_PENDING )
     {
+        if ( !async )
+            async = create_async ( obj, current, ptr );
+        if ( !async )
+            return;
+
+        async->status = STATUS_PENDING;
         if(!async->q)
         {
             async_add_timeout(async,timeout);
             async_insert(q, async);
+        }
     }
-}
+    else if ( async ) destroy_async ( async );
+    else set_error ( STATUS_INVALID_PARAMETER );

-    return q;
+    set_select_events ( obj, serial_get_poll_events ( obj ));
 }

 /* create a serial */








More information about the wine-patches mailing list