From 54ba272090f3768bc23850ffb97bd53a753d9dde Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Wed, 24 Apr 2002 21:29:54 +0000 Subject: [PATCH] Add more flexibility to the queue_async server call by moving most functionality into the object's queue_async method. --- server/async.c | 54 ++++++++++++++++++++----------------------------- server/file.c | 28 ++++++++++++++++++------- server/object.h | 4 ++-- server/serial.c | 37 ++++++++++++++++----------------- 4 files changed, 62 insertions(+), 61 deletions(-) diff --git a/server/async.c b/server/async.c index 9e44a0b80b..1b3448369f 100644 --- a/server/async.c +++ b/server/async.c @@ -150,42 +150,32 @@ void async_add_timeout(struct async *async, int timeout) 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 --git a/server/file.c b/server/file.c index 9b1df3e9ac..6908292273 100644 --- a/server/file.c +++ b/server/file.c @@ -69,7 +69,7 @@ static int file_get_fd( struct object *obj ); 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 @@ static int file_get_info( struct object *obj, struct get_file_info_reply *reply, 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 @@ static struct async_queue *file_queue_async(struct object *obj, struct async *as if ( !(file->flags & FILE_FLAG_OVERLAPPED) ) { set_error ( STATUS_INVALID_HANDLE ); - return NULL; + return; } switch(type) @@ -381,13 +382,26 @@ static struct async_queue *file_queue_async(struct object *obj, struct async *as 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 --git a/server/object.h b/server/object.h index 6ccbeafe5f..a904945b5b 100644 --- a/server/object.h +++ b/server/object.h @@ -63,8 +63,8 @@ struct object_ops 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 --git a/server/serial.c b/server/serial.c index 8fdce64efd..173c8c3f99 100644 --- a/server/serial.c +++ b/server/serial.c @@ -51,7 +51,7 @@ static void serial_dump( struct object *obj, int verbose ); 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 @@ static void serial_poll_event(struct object *obj, int event) 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 @@ static struct async_queue *serial_queue_async(struct object *obj, struct async * 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 */ -- 2.32.0.93.g670b81a890