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:
parent
0467b96c4f
commit
9ff0c09e38
|
@ -34,18 +34,16 @@ struct advise_sink
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SystemClockImpl {
|
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;
|
REFERENCE_TIME last_time;
|
||||||
BOOL adviseThreadActive;
|
CRITICAL_SECTION safe;
|
||||||
REFERENCE_TIME last_time;
|
|
||||||
CRITICAL_SECTION safe;
|
|
||||||
|
|
||||||
/* These lists are ordered by expiration time (soonest first). */
|
/* These lists are ordered by expiration time (soonest first). */
|
||||||
struct list single_sinks, periodic_sinks;
|
struct list single_sinks, periodic_sinks;
|
||||||
} SystemClockImpl;
|
} SystemClockImpl;
|
||||||
|
|
||||||
static inline SystemClockImpl *impl_from_IReferenceClock(IReferenceClock *iface)
|
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);
|
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 ... */
|
return 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
/*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);
|
||||||
|
}
|
||||||
|
clock->safe.DebugInfo->Spare[0] = 0;
|
||||||
|
DeleteCriticalSection(&clock->safe);
|
||||||
|
heap_free(clock);
|
||||||
}
|
}
|
||||||
This->safe.DebugInfo->Spare[0] = 0;
|
return refcount;
|
||||||
DeleteCriticalSection(&This->safe);
|
|
||||||
heap_free(This);
|
|
||||||
}
|
|
||||||
return ref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue