[PATCH 2/7] winhttp: Implement reference counting for tasks.

Paul Gofman wine at gitlab.winehq.org
Mon Jun 6 23:02:30 CDT 2022


From: Paul Gofman <pgofman at codeweavers.com>

---
 dlls/winhttp/request.c         | 32 +++++++++++++++++++++++++++-----
 dlls/winhttp/winhttp_private.h |  1 +
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index 9abe4f45598..70d727c7e2e 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -135,20 +135,41 @@ void stop_queue( struct queue *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 )
 {
+    struct task_header *task;
     struct list *entry;
 
     AcquireSRWLockExclusive( &queue->lock );
     assert( queue->callback_running );
     if (prev_task)
+    {
         list_remove( &prev_task->entry );
-
-    if (!(entry = list_head( &queue->queued_tasks )))
+        release_task( prev_task );
+    }
+    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;
+    }
     ReleaseSRWLockExclusive( &queue->lock );
-    if (!entry) return NULL;
-    return LIST_ENTRY( entry, struct task_header, entry );
+    return task;
 }
 
 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. */
         next_task = get_next_task( queue, task );
         release_object( task->obj );
-        free( task );
+        release_task( task );
         task = next_task;
     }
     TRACE( "instance %p exiting.\n", instance );
@@ -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);
     task_hdr->callback = task;
+    task_hdr->refs = 1;
     task_hdr->obj = obj;
     addref_object( obj );
 
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 4754d9258d1..ee3cdb78157 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -281,6 +281,7 @@ struct task_header
     struct list entry;
     TASK_CALLBACK callback;
     struct object_header *obj;
+    volatile LONG refs;
 };
 
 struct send_request
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/195



More information about the wine-devel mailing list