[PATCH 6/9] rtworkq: Add RtwqScheduleWorkItem().

Nikolay Sivov nsivov at codeweavers.com
Tue Feb 4 23:44:10 CST 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/rtworkq/queue.c      | 94 +++++++++++++++++++++++++++++++++++++++
 dlls/rtworkq/rtworkq.spec |  4 +-
 include/rtworkq.idl       |  2 +
 3 files changed, 98 insertions(+), 2 deletions(-)

diff --git a/dlls/rtworkq/queue.c b/dlls/rtworkq/queue.c
index 2797f292ce..dc6f6efeb1 100644
--- a/dlls/rtworkq/queue.c
+++ b/dlls/rtworkq/queue.c
@@ -428,6 +428,39 @@ static void CALLBACK waiting_item_cancelable_callback(TP_CALLBACK_INSTANCE *inst
     release_work_item(item);
 }
 
+static void CALLBACK scheduled_item_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
+{
+    struct work_item *item = context;
+
+    TRACE("result object %p.\n", item->result);
+
+    invoke_async_callback(item->result);
+
+    release_work_item(item);
+}
+
+static void CALLBACK scheduled_item_cancelable_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
+{
+    struct work_item *item = context;
+
+    TRACE("result object %p.\n", item->result);
+
+    queue_release_pending_item(item);
+
+    invoke_async_callback(item->result);
+
+    release_work_item(item);
+}
+
+static void CALLBACK periodic_item_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
+{
+    struct work_item *item = grab_work_item(context);
+
+    invoke_async_callback(item->result);
+
+    release_work_item(item);
+}
+
 static void queue_mark_item_pending(DWORD mask, struct work_item *item, RTWQWORKITEM_KEY *key)
 {
     *key = generate_item_key(mask);
@@ -465,6 +498,40 @@ static HRESULT queue_submit_wait(struct queue *queue, HANDLE event, LONG priorit
     return S_OK;
 }
 
+static HRESULT queue_submit_timer(struct queue *queue, IRtwqAsyncResult *result, INT64 timeout, DWORD period,
+        RTWQWORKITEM_KEY *key)
+{
+    PTP_TIMER_CALLBACK callback;
+    struct work_item *item;
+    FILETIME filetime;
+    LARGE_INTEGER t;
+
+    if (!(item = alloc_work_item(queue, result)))
+        return E_OUTOFMEMORY;
+
+    if (key)
+    {
+        queue_mark_item_pending(SCHEDULED_ITEM_KEY_MASK, item, key);
+    }
+
+    if (period)
+        callback = periodic_item_callback;
+    else
+        callback = key ? scheduled_item_cancelable_callback : scheduled_item_callback;
+
+    t.QuadPart = timeout * 1000 * 10;
+    filetime.dwLowDateTime = t.u.LowPart;
+    filetime.dwHighDateTime = t.u.HighPart;
+
+    item->u.timer_object = CreateThreadpoolTimer(callback, item,
+            (TP_CALLBACK_ENVIRON *)&queue->envs[TP_CALLBACK_PRIORITY_NORMAL]);
+    SetThreadpoolTimer(item->u.timer_object, &filetime, period, 0);
+
+    TRACE("dispatched %p.\n", result);
+
+    return S_OK;
+}
+
 static HRESULT queue_cancel_item(struct queue *queue, RTWQWORKITEM_KEY key)
 {
     HRESULT hr = RTWQ_E_NOT_FOUND;
@@ -751,6 +818,26 @@ HRESULT WINAPI RtwqPutWaitingWorkItem(HANDLE event, LONG priority, IRtwqAsyncRes
     return hr;
 }
 
+static HRESULT schedule_work_item(IRtwqAsyncResult *result, INT64 timeout, RTWQWORKITEM_KEY *key)
+{
+    struct queue *queue;
+    HRESULT hr;
+
+    if (FAILED(hr = grab_queue(RTWQ_CALLBACK_QUEUE_TIMER, &queue)))
+        return hr;
+
+    TRACE("%p, %s, %p.\n", result, wine_dbgstr_longlong(timeout), key);
+
+    return queue_submit_timer(queue, result, timeout, 0, key);
+}
+
+HRESULT WINAPI RtwqScheduleWorkItem(IRtwqAsyncResult *result, INT64 timeout, RTWQWORKITEM_KEY *key)
+{
+    TRACE("%p, %s, %p.\n", result, wine_dbgstr_longlong(timeout), key);
+
+    return schedule_work_item(result, timeout, key);
+}
+
 HRESULT WINAPI RtwqCancelWorkItem(RTWQWORKITEM_KEY key)
 {
     struct queue *queue;
@@ -764,6 +851,13 @@ HRESULT WINAPI RtwqCancelWorkItem(RTWQWORKITEM_KEY key)
     return queue_cancel_item(queue, key);
 }
 
+HRESULT WINAPI RtwqInvokeCallback(IRtwqAsyncResult *result)
+{
+    TRACE("%p.\n", result);
+
+    return invoke_async_callback(result);
+}
+
 HRESULT WINAPI RtwqLockWorkQueue(DWORD queue)
 {
     TRACE("%#x.\n", queue);
diff --git a/dlls/rtworkq/rtworkq.spec b/dlls/rtworkq/rtworkq.spec
index 04da2a9573..eb3d73d8e7 100644
--- a/dlls/rtworkq/rtworkq.spec
+++ b/dlls/rtworkq/rtworkq.spec
@@ -13,7 +13,7 @@
 @ stub RtwqGetWorkQueueMMCSSClass
 @ stub RtwqGetWorkQueueMMCSSPriority
 @ stub RtwqGetWorkQueueMMCSSTaskId
-@ stub RtwqInvokeCallback
+@ stdcall RtwqInvokeCallback(ptr)
 @ stub RtwqJoinWorkQueue
 @ stdcall RtwqLockPlatform()
 @ stub RtwqLockSharedWorkQueue
@@ -24,7 +24,7 @@
 @ stub RtwqRegisterPlatformEvents
 @ stub RtwqRegisterPlatformWithMMCSS
 @ stub RtwqRemovePeriodicCallback
-@ stub RtwqScheduleWorkItem
+@ stdcall RtwqScheduleWorkItem(ptr int64 ptr)
 @ stub RtwqSetDeadline
 @ stub RtwqSetDeadline2
 @ stub RtwqSetLongRunning
diff --git a/include/rtworkq.idl b/include/rtworkq.idl
index 8cc205a7eb..36468304b4 100644
--- a/include/rtworkq.idl
+++ b/include/rtworkq.idl
@@ -77,9 +77,11 @@ cpp_quote("} RTWQASYNCRESULT;")
 
 cpp_quote("HRESULT WINAPI RtwqCancelWorkItem(RTWQWORKITEM_KEY key);")
 cpp_quote("HRESULT WINAPI RtwqCreateAsyncResult(IUnknown *object, IRtwqAsyncCallback *callback, IUnknown *state, IRtwqAsyncResult **result);")
+cpp_quote("HRESULT WINAPI RtwqInvokeCallback(IRtwqAsyncResult *result);")
 cpp_quote("HRESULT WINAPI RtwqLockPlatform(void);")
 cpp_quote("HRESULT WINAPI RtwqLockWorkQueue(DWORD queue);")
 cpp_quote("HRESULT WINAPI RtwqPutWaitingWorkItem(HANDLE event, LONG priority, IRtwqAsyncResult *result, RTWQWORKITEM_KEY *key);")
+cpp_quote("HRESULT WINAPI RtwqScheduleWorkItem(IRtwqAsyncResult *result, INT64 timeout, RTWQWORKITEM_KEY *key);")
 cpp_quote("HRESULT WINAPI RtwqShutdown(void);")
 cpp_quote("HRESULT WINAPI RtwqStartup(void);")
 cpp_quote("HRESULT WINAPI RtwqUnlockPlatform(void);")
-- 
2.24.1




More information about the wine-devel mailing list