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

@ -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;
}