Commit 3d199dd9 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

winhttp: Implement reference counting for tasks.

parent 5d2f2797
...@@ -135,20 +135,41 @@ void stop_queue( struct queue *queue ) ...@@ -135,20 +135,41 @@ void stop_queue( struct queue *queue )
TRACE("stopped %p\n", queue); TRACE("stopped %p\n", queue);
} }
static void addref_task( struct task_header *task )
{
InterlockedIncrement( &task->refs );
}
static void release_task( struct task_header *task )
{
if (!InterlockedDecrement( &task->refs ))
free( task );
}
static struct task_header *get_next_task( struct queue *queue, struct task_header *prev_task ) static struct task_header *get_next_task( struct queue *queue, struct task_header *prev_task )
{ {
struct task_header *task;
struct list *entry; struct list *entry;
AcquireSRWLockExclusive( &queue->lock ); AcquireSRWLockExclusive( &queue->lock );
assert( queue->callback_running ); assert( queue->callback_running );
if (prev_task) if (prev_task)
{
list_remove( &prev_task->entry ); list_remove( &prev_task->entry );
release_task( prev_task );
if (!(entry = list_head( &queue->queued_tasks ))) }
if ((entry = list_head( &queue->queued_tasks )))
{
task = LIST_ENTRY( entry, struct task_header, entry );
addref_task( task );
}
else
{
task = NULL;
queue->callback_running = FALSE; queue->callback_running = FALSE;
}
ReleaseSRWLockExclusive( &queue->lock ); ReleaseSRWLockExclusive( &queue->lock );
if (!entry) return NULL; return task;
return LIST_ENTRY( entry, struct task_header, entry );
} }
static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx ) static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx )
...@@ -165,7 +186,7 @@ static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx ) ...@@ -165,7 +186,7 @@ static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx )
/* Queue object may be freed by release_object() unless there is another task referencing it. */ /* Queue object may be freed by release_object() unless there is another task referencing it. */
next_task = get_next_task( queue, task ); next_task = get_next_task( queue, task );
release_object( task->obj ); release_object( task->obj );
free( task ); release_task( task );
task = next_task; task = next_task;
} }
TRACE( "instance %p exiting.\n", instance ); TRACE( "instance %p exiting.\n", instance );
...@@ -178,6 +199,7 @@ static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_he ...@@ -178,6 +199,7 @@ static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_he
TRACE("queueing %p in %p\n", task_hdr, queue); TRACE("queueing %p in %p\n", task_hdr, queue);
task_hdr->callback = task; task_hdr->callback = task;
task_hdr->refs = 1;
task_hdr->obj = obj; task_hdr->obj = obj;
addref_object( obj ); addref_object( obj );
......
...@@ -281,6 +281,7 @@ struct task_header ...@@ -281,6 +281,7 @@ struct task_header
struct list entry; struct list entry;
TASK_CALLBACK callback; TASK_CALLBACK callback;
struct object_header *obj; struct object_header *obj;
volatile LONG refs;
}; };
struct send_request struct send_request
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment