[PATCH 3/5] quartz/systemclock: Simplify notifying the advise thread.
Zebediah Figura
z.figura12 at gmail.com
Thu Mar 14 19:10:59 CDT 2019
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
dlls/quartz/systemclock.c | 127 +++++++++++++-------------------------
1 file changed, 43 insertions(+), 84 deletions(-)
diff --git a/dlls/quartz/systemclock.c b/dlls/quartz/systemclock.c
index 511abf66fb..8291fe5fb2 100644
--- a/dlls/quartz/systemclock.c
+++ b/dlls/quartz/systemclock.c
@@ -34,18 +34,16 @@ struct advise_sink
};
typedef struct SystemClockImpl {
- IReferenceClock IReferenceClock_iface;
- LONG ref;
+ IReferenceClock IReferenceClock_iface;
+ LONG ref;
- /** IReferenceClock */
- HANDLE adviseThread;
- DWORD adviseThreadId;
- BOOL adviseThreadActive;
- REFERENCE_TIME last_time;
- CRITICAL_SECTION safe;
+ BOOL thread_created;
+ HANDLE thread, notify_event, stop_event;
+ REFERENCE_TIME last_time;
+ CRITICAL_SECTION safe;
- /* These lists are ordered by expiration time (soonest first). */
- struct list single_sinks, periodic_sinks;
+ /* These lists are ordered by expiration time (soonest first). */
+ struct list single_sinks, periodic_sinks;
} SystemClockImpl;
static inline SystemClockImpl *impl_from_IReferenceClock(IReferenceClock *iface)
@@ -70,25 +68,17 @@ static void insert_advise_sink(struct advise_sink *sink, struct list *queue)
list_add_tail(queue, &sink->entry);
}
-#define MAX_REFTIME (REFERENCE_TIME)(0x7FFFFFFFFFFFFFFF)
-#define ADVISE_EXIT (WM_APP + 0)
-#define ADVISE_REMOVE (WM_APP + 2)
-#define ADVISE_ADD_SINGLESHOT (WM_APP + 4)
-#define ADVISE_ADD_PERIODIC (WM_APP + 8)
-
static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
SystemClockImpl* This = lpParam;
struct advise_sink *sink, *cursor;
struct list *entry;
DWORD timeOut = INFINITE;
- MSG msg;
REFERENCE_TIME curTime;
+ HANDLE handles[2] = {This->stop_event, This->notify_event};
TRACE("(%p): Main Loop\n", This);
while (TRUE) {
- if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
-
EnterCriticalSection(&This->safe);
curTime = GetTickCount64() * 10000;
@@ -124,58 +114,21 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
}
LeaveCriticalSection(&This->safe);
-
- while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
- /** if hwnd we suppose that is a windows event ... */
- if (NULL != msg.hwnd) {
- TranslateMessage(&msg);
- DispatchMessageW(&msg);
- } else {
- switch (msg.message) {
- case WM_QUIT:
- case ADVISE_EXIT:
- goto outofthread;
- case ADVISE_ADD_SINGLESHOT:
- case ADVISE_ADD_PERIODIC:
- /** set timeout to 0 to do a rescan now */
- timeOut = 0;
- break;
- case ADVISE_REMOVE:
- /** hmmmm what we can do here ... */
- timeOut = INFINITE;
- break;
- default:
- ERR("Unhandled message %u. Critical Path\n", msg.message);
- break;
- }
- }
- }
- }
-outofthread:
- TRACE("(%p): Exiting\n", This);
- return 0;
+ if (WaitForMultipleObjects(2, handles, FALSE, timeOut) == 0)
+ return 0;
+ }
}
-/*static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) { */
-static BOOL SystemClockPostMessageToAdviseThread(SystemClockImpl* This, UINT iMsg) {
- if (FALSE == This->adviseThreadActive) {
- BOOL res;
- This->adviseThread = CreateThread(NULL, 0, SystemClockAdviseThread, This, 0, &This->adviseThreadId);
- if (NULL == This->adviseThread) return FALSE;
- SetThreadPriority(This->adviseThread, THREAD_PRIORITY_TIME_CRITICAL);
- This->adviseThreadActive = TRUE;
- while(1) {
- res = PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0);
- /* Let the thread creates its message queue (with MsgWaitForMultipleObjects call) by yielding and retrying */
- if (!res && (GetLastError() == ERROR_INVALID_THREAD_ID))
- Sleep(0);
- else
- break;
+static void notify_thread(SystemClockImpl *clock)
+{
+ if (!InterlockedCompareExchange(&clock->thread_created, TRUE, FALSE))
+ {
+ clock->thread = CreateThread(NULL, 0, SystemClockAdviseThread, clock, 0, NULL);
+ clock->notify_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+ clock->stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
}
- return res;
- }
- return PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0);
+ SetEvent(clock->notify_event);
}
static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) {
@@ -203,20 +156,28 @@ static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REF
return E_NOINTERFACE;
}
-static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) {
- SystemClockImpl *This = impl_from_IReferenceClock(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
- TRACE("(%p): ReleaseRef to %d\n", This, ref);
- if (ref == 0) {
- if (This->adviseThreadActive && SystemClockPostMessageToAdviseThread(This, ADVISE_EXIT)) {
- WaitForSingleObject(This->adviseThread, INFINITE);
- CloseHandle(This->adviseThread);
+static ULONG WINAPI SystemClockImpl_Release(IReferenceClock *iface)
+{
+ SystemClockImpl *clock = impl_from_IReferenceClock(iface);
+ ULONG refcount = InterlockedDecrement(&clock->ref);
+
+ TRACE("%p decreasing refcount to %u.\n", clock, refcount);
+
+ if (!refcount)
+ {
+ if (clock->thread)
+ {
+ SetEvent(clock->stop_event);
+ WaitForSingleObject(clock->thread, INFINITE);
+ CloseHandle(clock->thread);
+ CloseHandle(clock->notify_event);
+ CloseHandle(clock->stop_event);
+ }
+ clock->safe.DebugInfo->Spare[0] = 0;
+ DeleteCriticalSection(&clock->safe);
+ heap_free(clock);
}
- This->safe.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->safe);
- heap_free(This);
- }
- return ref;
+ return refcount;
}
static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock *iface, REFERENCE_TIME *time)
@@ -272,7 +233,7 @@ static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock *iface,
insert_advise_sink(sink, &clock->single_sinks);
LeaveCriticalSection(&clock->safe);
- SystemClockPostMessageToAdviseThread(clock, ADVISE_ADD_SINGLESHOT);
+ notify_thread(clock);
*cookie = (DWORD_PTR)sink;
return S_OK;
@@ -307,7 +268,7 @@ static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface,
insert_advise_sink(sink, &clock->periodic_sinks);
LeaveCriticalSection(&clock->safe);
- SystemClockPostMessageToAdviseThread(clock, ADVISE_ADD_PERIODIC);
+ notify_thread(clock);
*cookie = (DWORD_PTR)sink;
return S_OK;
@@ -328,7 +289,6 @@ static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock *iface, DWORD_PTR
{
list_remove(&sink->entry);
heap_free(sink);
- SystemClockPostMessageToAdviseThread(clock, ADVISE_REMOVE);
LeaveCriticalSection(&clock->safe);
return S_OK;
}
@@ -340,7 +300,6 @@ static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock *iface, DWORD_PTR
{
list_remove(&sink->entry);
heap_free(sink);
- SystemClockPostMessageToAdviseThread(clock, ADVISE_REMOVE);
LeaveCriticalSection(&clock->safe);
return S_OK;
}
--
2.20.1
More information about the wine-devel
mailing list