[PATCH v2 3/3] winhttp: Use default thread pool.
Paul Gofman
pgofman at codeweavers.com
Tue Mar 15 11:07:25 CDT 2022
Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
v2:
- no changes.
dlls/winhttp/request.c | 86 +++++++++++++++++++++++-----------
dlls/winhttp/session.c | 1 +
dlls/winhttp/winhttp_private.h | 7 ++-
3 files changed, 64 insertions(+), 30 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c
index a825ac71d33..fe703c19109 100644
--- a/dlls/winhttp/request.c
+++ b/dlls/winhttp/request.c
@@ -122,54 +122,82 @@ static const WCHAR *attribute_table[] =
NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */
};
-static DWORD start_queue( struct queue *queue )
+void init_queue( struct queue *queue )
{
- if (queue->pool) return ERROR_SUCCESS;
-
- if (!(queue->pool = CreateThreadpool( NULL ))) return GetLastError();
- SetThreadpoolThreadMinimum( queue->pool, 1 );
- SetThreadpoolThreadMaximum( queue->pool, 1 );
-
- memset( &queue->env, 0, sizeof(queue->env) );
- queue->env.Version = 1;
- queue->env.Pool = queue->pool;
-
- TRACE("started %p\n", queue);
- return ERROR_SUCCESS;
+ InitializeSRWLock( &queue->lock );
+ list_init( &queue->queued_tasks );
+ queue->callback_running = FALSE;
}
void stop_queue( struct queue *queue )
{
- if (!queue->pool) return;
- CloseThreadpool( queue->pool );
- queue->pool = NULL;
+ assert( list_empty( &queue->queued_tasks ));
TRACE("stopped %p\n", queue);
}
-static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx, TP_WORK *work )
+static struct task_header *get_next_task( struct queue *queue )
{
- struct task_header *task_hdr = ctx;
+ struct list *entry;
- task_hdr->callback( task_hdr );
- release_object( task_hdr->obj );
- free( task_hdr );
+ AcquireSRWLockExclusive( &queue->lock );
+ assert( queue->callback_running );
+ if ((entry = list_head( &queue->queued_tasks )))
+ list_remove( entry );
+ else
+ queue->callback_running = FALSE;
+ ReleaseSRWLockExclusive( &queue->lock );
+ if (!entry) return NULL;
+ return LIST_ENTRY( entry, struct task_header, entry );
+}
+
+static void CALLBACK task_callback( TP_CALLBACK_INSTANCE *instance, void *ctx )
+{
+ struct task_header *task, *next_task;
+ struct queue *queue = ctx;
+
+ TRACE( "instance %p.\n", instance );
+
+ task = get_next_task( queue );
+ while (task)
+ {
+ task->callback( task );
+ /* Queue object may be freed by release_object() unless there is another task referencing it. */
+ next_task = get_next_task( queue );
+ release_object( task->obj );
+ free( task );
+ task = next_task;
+ }
+ TRACE( "instance %p exiting.\n", instance );
}
static DWORD queue_task( struct queue *queue, TASK_CALLBACK task, struct task_header *task_hdr,
struct object_header *obj )
{
- TP_WORK *work;
- DWORD ret;
-
- if ((ret = start_queue( queue ))) return ret;
+ BOOL callback_running;
- if (!(work = CreateThreadpoolWork( task_callback, task_hdr, &queue->env ))) return GetLastError();
TRACE("queueing %p in %p\n", task_hdr, queue);
task_hdr->callback = task;
task_hdr->obj = obj;
addref_object( obj );
- SubmitThreadpoolWork( work );
- CloseThreadpoolWork( work );
+
+ AcquireSRWLockExclusive( &queue->lock );
+ list_add_tail( &queue->queued_tasks, &task_hdr->entry );
+ if (!(callback_running = queue->callback_running))
+ {
+ if ((queue->callback_running = TrySubmitThreadpoolCallback( task_callback, queue, NULL )))
+ callback_running = TRUE;
+ else
+ list_remove( &task_hdr->entry );
+ }
+ ReleaseSRWLockExclusive( &queue->lock );
+
+ if (!callback_running)
+ {
+ release_object( obj );
+ free( task_hdr );
+ ERR( "Submiting threadpool callback failed, err %lu.\n", GetLastError() );
+ return ERROR_OUTOFMEMORY;
+ }
return ERROR_SUCCESS;
}
@@ -3096,6 +3124,8 @@ HINTERNET WINAPI WinHttpWebSocketCompleteUpgrade( HINTERNET hrequest, DWORD_PTR
socket->hdr.notify_mask = request->hdr.notify_mask;
socket->hdr.context = context;
InitializeSRWLock( &socket->send_lock );
+ init_queue( &socket->send_q );
+ init_queue( &socket->recv_q );
addref_object( &request->hdr );
socket->request = request;
diff --git a/dlls/winhttp/session.c b/dlls/winhttp/session.c
index 7c55adb8475..3b00d2448d1 100644
--- a/dlls/winhttp/session.c
+++ b/dlls/winhttp/session.c
@@ -1160,6 +1160,7 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, const WCHAR *verb, cons
request->hdr.notify_mask = connect->hdr.notify_mask;
request->hdr.context = connect->hdr.context;
request->hdr.redirect_policy = connect->hdr.redirect_policy;
+ init_queue( &request->queue );
addref_object( &connect->hdr );
request->connect = connect;
diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h
index 35f3e64b5a3..4754d9258d1 100644
--- a/dlls/winhttp/winhttp_private.h
+++ b/dlls/winhttp/winhttp_private.h
@@ -159,8 +159,9 @@ struct authinfo
struct queue
{
- TP_POOL *pool;
- TP_CALLBACK_ENVIRON env;
+ SRWLOCK lock;
+ struct list queued_tasks;
+ BOOL callback_running;
};
enum request_flags
@@ -277,6 +278,7 @@ typedef void (*TASK_CALLBACK)( void *ctx );
struct task_header
{
+ struct list entry;
TASK_CALLBACK callback;
struct object_header *obj;
};
@@ -355,6 +357,7 @@ BOOL free_handle( HINTERNET ) DECLSPEC_HIDDEN;
void send_callback( struct object_header *, DWORD, LPVOID, DWORD ) DECLSPEC_HIDDEN;
void close_connection( struct request * ) DECLSPEC_HIDDEN;
+void init_queue( struct queue *queue ) DECLSPEC_HIDDEN;
void stop_queue( struct queue * ) DECLSPEC_HIDDEN;
void netconn_close( struct netconn * ) DECLSPEC_HIDDEN;
--
2.35.1
More information about the wine-devel
mailing list