quartz/systemclock: Simplify notifying the advise thread.

Signed-off-by: Zebediah Figura <z.figura12@gmail.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Zebediah Figura 2019-03-14 19:10:59 -05:00 committed by Alexandre Julliard
parent 0467b96c4f
commit 9ff0c09e38
1 changed files with 43 additions and 84 deletions

View File

@ -37,10 +37,8 @@ typedef struct SystemClockImpl {
IReferenceClock IReferenceClock_iface; IReferenceClock IReferenceClock_iface;
LONG ref; LONG ref;
/** IReferenceClock */ BOOL thread_created;
HANDLE adviseThread; HANDLE thread, notify_event, stop_event;
DWORD adviseThreadId;
BOOL adviseThreadActive;
REFERENCE_TIME last_time; REFERENCE_TIME last_time;
CRITICAL_SECTION safe; CRITICAL_SECTION safe;
@ -70,25 +68,17 @@ static void insert_advise_sink(struct advise_sink *sink, struct list *queue)
list_add_tail(queue, &sink->entry); 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) { static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
SystemClockImpl* This = lpParam; SystemClockImpl* This = lpParam;
struct advise_sink *sink, *cursor; struct advise_sink *sink, *cursor;
struct list *entry; struct list *entry;
DWORD timeOut = INFINITE; DWORD timeOut = INFINITE;
MSG msg;
REFERENCE_TIME curTime; REFERENCE_TIME curTime;
HANDLE handles[2] = {This->stop_event, This->notify_event};
TRACE("(%p): Main Loop\n", This); TRACE("(%p): Main Loop\n", This);
while (TRUE) { while (TRUE) {
if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
EnterCriticalSection(&This->safe); EnterCriticalSection(&This->safe);
curTime = GetTickCount64() * 10000; curTime = GetTickCount64() * 10000;
@ -125,57 +115,20 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
LeaveCriticalSection(&This->safe); LeaveCriticalSection(&This->safe);
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { if (WaitForMultipleObjects(2, handles, FALSE, timeOut) == 0)
/** 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; return 0;
} }
/*static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) { */ }
static BOOL SystemClockPostMessageToAdviseThread(SystemClockImpl* This, UINT iMsg) { static void notify_thread(SystemClockImpl *clock)
if (FALSE == This->adviseThreadActive) { {
BOOL res; if (!InterlockedCompareExchange(&clock->thread_created, TRUE, FALSE))
This->adviseThread = CreateThread(NULL, 0, SystemClockAdviseThread, This, 0, &This->adviseThreadId); {
if (NULL == This->adviseThread) return FALSE; clock->thread = CreateThread(NULL, 0, SystemClockAdviseThread, clock, 0, NULL);
SetThreadPriority(This->adviseThread, THREAD_PRIORITY_TIME_CRITICAL); clock->notify_event = CreateEventW(NULL, FALSE, FALSE, NULL);
This->adviseThreadActive = TRUE; clock->stop_event = CreateEventW(NULL, TRUE, FALSE, NULL);
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;
} }
return res; SetEvent(clock->notify_event);
}
return PostThreadMessageW(This->adviseThreadId, iMsg, 0, 0);
} }
static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) { static ULONG WINAPI SystemClockImpl_AddRef(IReferenceClock* iface) {
@ -203,20 +156,28 @@ static HRESULT WINAPI SystemClockImpl_QueryInterface(IReferenceClock* iface, REF
return E_NOINTERFACE; return E_NOINTERFACE;
} }
static ULONG WINAPI SystemClockImpl_Release(IReferenceClock* iface) { static ULONG WINAPI SystemClockImpl_Release(IReferenceClock *iface)
SystemClockImpl *This = impl_from_IReferenceClock(iface); {
ULONG ref = InterlockedDecrement(&This->ref); SystemClockImpl *clock = impl_from_IReferenceClock(iface);
TRACE("(%p): ReleaseRef to %d\n", This, ref); ULONG refcount = InterlockedDecrement(&clock->ref);
if (ref == 0) {
if (This->adviseThreadActive && SystemClockPostMessageToAdviseThread(This, ADVISE_EXIT)) { TRACE("%p decreasing refcount to %u.\n", clock, refcount);
WaitForSingleObject(This->adviseThread, INFINITE);
CloseHandle(This->adviseThread); if (!refcount)
{
if (clock->thread)
{
SetEvent(clock->stop_event);
WaitForSingleObject(clock->thread, INFINITE);
CloseHandle(clock->thread);
CloseHandle(clock->notify_event);
CloseHandle(clock->stop_event);
} }
This->safe.DebugInfo->Spare[0] = 0; clock->safe.DebugInfo->Spare[0] = 0;
DeleteCriticalSection(&This->safe); DeleteCriticalSection(&clock->safe);
heap_free(This); heap_free(clock);
} }
return ref; return refcount;
} }
static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock *iface, REFERENCE_TIME *time) 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); insert_advise_sink(sink, &clock->single_sinks);
LeaveCriticalSection(&clock->safe); LeaveCriticalSection(&clock->safe);
SystemClockPostMessageToAdviseThread(clock, ADVISE_ADD_SINGLESHOT); notify_thread(clock);
*cookie = (DWORD_PTR)sink; *cookie = (DWORD_PTR)sink;
return S_OK; return S_OK;
@ -307,7 +268,7 @@ static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface,
insert_advise_sink(sink, &clock->periodic_sinks); insert_advise_sink(sink, &clock->periodic_sinks);
LeaveCriticalSection(&clock->safe); LeaveCriticalSection(&clock->safe);
SystemClockPostMessageToAdviseThread(clock, ADVISE_ADD_PERIODIC); notify_thread(clock);
*cookie = (DWORD_PTR)sink; *cookie = (DWORD_PTR)sink;
return S_OK; return S_OK;
@ -328,7 +289,6 @@ static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock *iface, DWORD_PTR
{ {
list_remove(&sink->entry); list_remove(&sink->entry);
heap_free(sink); heap_free(sink);
SystemClockPostMessageToAdviseThread(clock, ADVISE_REMOVE);
LeaveCriticalSection(&clock->safe); LeaveCriticalSection(&clock->safe);
return S_OK; return S_OK;
} }
@ -340,7 +300,6 @@ static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock *iface, DWORD_PTR
{ {
list_remove(&sink->entry); list_remove(&sink->entry);
heap_free(sink); heap_free(sink);
SystemClockPostMessageToAdviseThread(clock, ADVISE_REMOVE);
LeaveCriticalSection(&clock->safe); LeaveCriticalSection(&clock->safe);
return S_OK; return S_OK;
} }