Nikolay Sivov : rtworkq: Use IUnknown wrapper for work item management.

Alexandre Julliard julliard at winehq.org
Tue Feb 11 15:44:55 CST 2020


Module: wine
Branch: master
Commit: a4143e211c1b5f69e7f9f8edd2fd894eb3173d79
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=a4143e211c1b5f69e7f9f8edd2fd894eb3173d79

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Tue Feb 11 12:19:04 2020 +0300

rtworkq: Use IUnknown wrapper for work item management.

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/rtworkq/queue.c | 83 +++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 59 insertions(+), 24 deletions(-)

diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c
index a2fb3824c3..866c2b532f 100644
--- a/dlls/rtworkq/queue.c
+++ b/dlls/rtworkq/queue.c
@@ -109,8 +109,9 @@ enum system_queue_index
 
 struct work_item
 {
-    struct list entry;
+    IUnknown IUnknown_iface;
     LONG refcount;
+    struct list entry;
     IRtwqAsyncResult *result;
     struct queue *queue;
     RTWQWORKITEM_KEY key;
@@ -121,6 +122,11 @@ struct work_item
     } u;
 };
 
+static struct work_item *work_item_impl_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, struct work_item, IUnknown_iface);
+}
+
 static const TP_CALLBACK_PRIORITY priorities[] =
 {
     TP_CALLBACK_PRIORITY_HIGH,
@@ -158,32 +164,59 @@ static void CALLBACK standard_queue_cleanup_callback(void *object_data, void *gr
 {
 }
 
-static struct work_item * alloc_work_item(struct queue *queue, IRtwqAsyncResult *result)
+static HRESULT WINAPI work_item_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
 {
-    struct work_item *item;
+    if (IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IUnknown_AddRef(iface);
+        return S_OK;
+    }
 
-    item = heap_alloc_zero(sizeof(*item));
-    item->result = result;
-    IRtwqAsyncResult_AddRef(item->result);
-    item->refcount = 1;
-    item->queue = queue;
-    list_init(&item->entry);
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
 
-    return item;
+static ULONG WINAPI work_item_AddRef(IUnknown *iface)
+{
+    struct work_item *item = work_item_impl_from_IUnknown(iface);
+    return InterlockedIncrement(&item->refcount);
 }
 
-static void release_work_item(struct work_item *item)
+static ULONG WINAPI work_item_Release(IUnknown *iface)
 {
-    if (InterlockedDecrement(&item->refcount) == 0)
+    struct work_item *item = work_item_impl_from_IUnknown(iface);
+    ULONG refcount = InterlockedDecrement(&item->refcount);
+
+    if (!refcount)
     {
          IRtwqAsyncResult_Release(item->result);
          heap_free(item);
     }
+
+    return refcount;
 }
 
-static struct work_item *grab_work_item(struct work_item *item)
+static const IUnknownVtbl work_item_vtbl =
 {
-    InterlockedIncrement(&item->refcount);
+    work_item_QueryInterface,
+    work_item_AddRef,
+    work_item_Release,
+};
+
+static struct work_item * alloc_work_item(struct queue *queue, IRtwqAsyncResult *result)
+{
+    struct work_item *item;
+
+    item = heap_alloc_zero(sizeof(*item));
+
+    item->IUnknown_iface.lpVtbl = &work_item_vtbl;
+    item->result = result;
+    IRtwqAsyncResult_AddRef(item->result);
+    item->refcount = 1;
+    item->queue = queue;
+    list_init(&item->entry);
+
     return item;
 }
 
@@ -294,7 +327,7 @@ static void shutdown_queue(struct queue *queue)
     LIST_FOR_EACH_ENTRY_SAFE(item, item2, &queue->pending_items, struct work_item, entry)
     {
         list_remove(&item->entry);
-        release_work_item(item);
+        IUnknown_Release(&item->IUnknown_iface);
     }
     LeaveCriticalSection(&queue->cs);
 
@@ -335,7 +368,7 @@ static void CALLBACK standard_queue_worker(TP_CALLBACK_INSTANCE *instance, void
 
     IRtwqAsyncCallback_Invoke(result->pCallback, item->result);
 
-    release_work_item(item);
+    IUnknown_Release(&item->IUnknown_iface);
 }
 
 static HRESULT queue_submit_item(struct queue *queue, LONG priority, IRtwqAsyncResult *result)
@@ -399,7 +432,7 @@ static void queue_release_pending_item(struct work_item *item)
     {
         list_remove(&item->entry);
         item->key = 0;
-        release_work_item(item);
+        IUnknown_Release(&item->IUnknown_iface);
     }
     LeaveCriticalSection(&item->queue->cs);
 }
@@ -413,7 +446,7 @@ static void CALLBACK waiting_item_callback(TP_CALLBACK_INSTANCE *instance, void
 
     invoke_async_callback(item->result);
 
-    release_work_item(item);
+    IUnknown_Release(&item->IUnknown_iface);
 }
 
 static void CALLBACK waiting_item_cancelable_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_WAIT *wait,
@@ -427,7 +460,7 @@ static void CALLBACK waiting_item_cancelable_callback(TP_CALLBACK_INSTANCE *inst
 
     invoke_async_callback(item->result);
 
-    release_work_item(item);
+    IUnknown_Release(&item->IUnknown_iface);
 }
 
 static void CALLBACK scheduled_item_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
@@ -438,7 +471,7 @@ static void CALLBACK scheduled_item_callback(TP_CALLBACK_INSTANCE *instance, voi
 
     invoke_async_callback(item->result);
 
-    release_work_item(item);
+    IUnknown_Release(&item->IUnknown_iface);
 }
 
 static void CALLBACK scheduled_item_cancelable_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
@@ -451,16 +484,18 @@ static void CALLBACK scheduled_item_cancelable_callback(TP_CALLBACK_INSTANCE *in
 
     invoke_async_callback(item->result);
 
-    release_work_item(item);
+    IUnknown_Release(&item->IUnknown_iface);
 }
 
 static void CALLBACK periodic_item_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
 {
-    struct work_item *item = grab_work_item(context);
+    struct work_item *item = context;
+
+    IUnknown_AddRef(&item->IUnknown_iface);
 
     invoke_async_callback(item->result);
 
-    release_work_item(item);
+    IUnknown_Release(&item->IUnknown_iface);
 }
 
 static void queue_mark_item_pending(DWORD mask, struct work_item *item, RTWQWORKITEM_KEY *key)
@@ -470,7 +505,7 @@ static void queue_mark_item_pending(DWORD mask, struct work_item *item, RTWQWORK
 
     EnterCriticalSection(&item->queue->cs);
     list_add_tail(&item->queue->pending_items, &item->entry);
-    grab_work_item(item);
+    IUnknown_AddRef(&item->IUnknown_iface);
     LeaveCriticalSection(&item->queue->cs);
 }
 




More information about the wine-cvs mailing list