Add more flexibility to the queue_async server call by moving most
functionality into the object's queue_async method.
This commit is contained in:
parent
14a913c28d
commit
54ba272090
|
@ -150,42 +150,32 @@ void async_add_timeout(struct async *async, int timeout)
|
||||||
|
|
||||||
DECL_HANDLER(register_async)
|
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)) )
|
if ( !(obj) || !obj->ops->queue_async )
|
||||||
return;
|
|
||||||
|
|
||||||
if(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);
|
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);
|
release_object(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ static int file_get_fd( struct object *obj );
|
||||||
static int file_flush( 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 int file_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
|
||||||
static void file_destroy( struct object *obj );
|
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 =
|
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;
|
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 file *file = (struct file *)obj;
|
||||||
|
struct async *async;
|
||||||
struct async_queue *q;
|
struct async_queue *q;
|
||||||
|
|
||||||
assert( obj->ops == &file_ops );
|
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) )
|
if ( !(file->flags & FILE_FLAG_OVERLAPPED) )
|
||||||
{
|
{
|
||||||
set_error ( STATUS_INVALID_HANDLE );
|
set_error ( STATUS_INVALID_HANDLE );
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
|
@ -381,13 +382,26 @@ static struct async_queue *file_queue_async(struct object *obj, struct async *as
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
set_error( STATUS_INVALID_PARAMETER );
|
set_error( STATUS_INVALID_PARAMETER );
|
||||||
return NULL;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(async && !async->q)
|
async = find_async ( q, current, ptr );
|
||||||
async_insert(q, async);
|
|
||||||
|
|
||||||
return q;
|
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 );
|
||||||
|
|
||||||
|
set_select_events ( obj, file_get_poll_events ( obj ));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void file_destroy( struct object *obj )
|
static void file_destroy( struct object *obj )
|
||||||
|
|
|
@ -63,8 +63,8 @@ struct object_ops
|
||||||
int (*flush)(struct object *);
|
int (*flush)(struct object *);
|
||||||
/* get file information */
|
/* get file information */
|
||||||
int (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags);
|
int (*get_file_info)(struct object *,struct get_file_info_reply *, int *flags);
|
||||||
/* queue an async operation */
|
/* queue an async operation - see register_async handler in async.c*/
|
||||||
struct async_queue* (*queue_async)(struct object *, struct async *async, int type, int count);
|
void (*queue_async)(struct object *, void* ptr, unsigned int status, int type, int count);
|
||||||
/* destroy on refcount == 0 */
|
/* destroy on refcount == 0 */
|
||||||
void (*destroy)(struct object *);
|
void (*destroy)(struct object *);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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_fd( struct object *obj );
|
||||||
static int serial_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags );
|
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 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 destroy_serial(struct object *obj);
|
||||||
static void serial_poll_event( struct object *obj, int event );
|
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));
|
set_select_events(obj,obj->ops->get_poll_events(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void serial_queue_async(struct object *obj, void *ptr, unsigned int status, int type, int count)
|
||||||
* 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)
|
|
||||||
{
|
{
|
||||||
struct serial *serial = (struct serial *)obj;
|
struct serial *serial = (struct serial *)obj;
|
||||||
struct async_queue *q;
|
struct async_queue *q;
|
||||||
|
struct async *async;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
|
||||||
assert(obj->ops == &serial_ops);
|
assert(obj->ops == &serial_ops);
|
||||||
|
@ -288,19 +275,29 @@ static struct async_queue *serial_queue_async(struct object *obj, struct async *
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
set_error(STATUS_INVALID_PARAMETER);
|
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)
|
if(!async->q)
|
||||||
{
|
{
|
||||||
async_add_timeout(async,timeout);
|
async_add_timeout(async,timeout);
|
||||||
async_insert(q, async);
|
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 */
|
/* create a serial */
|
||||||
|
|
Loading…
Reference in New Issue