Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/quartz/systemclock.c | 258 +++++++++++++++++++-------------------
1 file changed, 128 insertions(+), 130 deletions(-)
diff --git a/dlls/quartz/systemclock.c b/dlls/quartz/systemclock.c
index e9f13b5130..d95bd3ab3a 100644
--- a/dlls/quartz/systemclock.c
+++ b/dlls/quartz/systemclock.c
@@ -26,14 +26,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(quartz);
-typedef struct SystemClockAdviseEntry SystemClockAdviseEntry;
-struct SystemClockAdviseEntry {
- SystemClockAdviseEntry* next;
- SystemClockAdviseEntry* prev;
-
- HANDLE hEvent;
- REFERENCE_TIME rtBaseTime;
- REFERENCE_TIME rtIntervalTime;
+struct advise_sink
+{
+ struct list entry;
+ HANDLE hEvent;
+ REFERENCE_TIME rtBaseTime, rtIntervalTime;
};
typedef struct SystemClockImpl {
@@ -47,8 +44,8 @@ typedef struct SystemClockImpl {
REFERENCE_TIME last_time;
CRITICAL_SECTION safe;
- SystemClockAdviseEntry* pSingleShotAdvise;
- SystemClockAdviseEntry* pPeriodicAdvise;
+ /* These lists are ordered by expiration time (soonest first). */
+ struct list single_sinks, periodic_sinks;
} SystemClockImpl;
static inline SystemClockImpl *impl_from_IReferenceClock(IReferenceClock *iface)
@@ -56,34 +53,21 @@ static inline SystemClockImpl *impl_from_IReferenceClock(IReferenceClock *iface)
return CONTAINING_RECORD(iface, SystemClockImpl, IReferenceClock_iface);
}
+static void insert_advise_sink(struct advise_sink *sink, struct list *queue)
+{
+ REFERENCE_TIME due_time = sink->rtBaseTime + sink->rtIntervalTime;
+ struct advise_sink *cursor;
-static void QUARTZ_RemoveAviseEntryFromQueue(SystemClockImpl* This, SystemClockAdviseEntry* pEntry) {
- if (pEntry->prev) pEntry->prev->next = pEntry->next;
- if (pEntry->next) pEntry->next->prev = pEntry->prev;
- if (This->pSingleShotAdvise == pEntry) This->pSingleShotAdvise = pEntry->next;
- if (This->pPeriodicAdvise == pEntry) This->pPeriodicAdvise = pEntry->next;
-}
+ LIST_FOR_EACH_ENTRY(cursor, queue, struct advise_sink, entry)
+ {
+ if (cursor->rtBaseTime + cursor->rtIntervalTime > due_time)
+ {
+ list_add_before(&cursor->entry, &sink->entry);
+ return;
+ }
+ }
-static void QUARTZ_InsertAviseEntryFromQueue(SystemClockImpl* This, SystemClockAdviseEntry* pEntry, SystemClockAdviseEntry** pQueue) {
- SystemClockAdviseEntry* prev_it = NULL;
- SystemClockAdviseEntry* it = NULL;
- REFERENCE_TIME bornTime = pEntry->rtBaseTime + pEntry->rtIntervalTime;
-
- for (it = *pQueue; NULL != it && (it->rtBaseTime + it->rtIntervalTime) < bornTime; it = it->next) {
- prev_it = it;
- }
- if (NULL == prev_it) {
- pEntry->prev = NULL;
- if (NULL != (*pQueue)) pEntry->next = (*pQueue)->next;
- /*assert( NULL == pEntry->next->prev );*/
- if (NULL != pEntry->next) pEntry->next->prev = pEntry;
- (*pQueue) = pEntry;
- } else {
- pEntry->prev = prev_it;
- pEntry->next = prev_it->next;
- prev_it->next = pEntry;
- if (NULL != pEntry->next) pEntry->next->prev = pEntry;
- }
+ list_add_tail(queue, &sink->entry);
}
#define MAX_REFTIME (REFERENCE_TIME)(0x7FFFFFFFFFFFFFFF)
@@ -94,12 +78,12 @@ static void QUARTZ_InsertAviseEntryFromQueue(SystemClockImpl* This, SystemClockA
static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
SystemClockImpl* This = lpParam;
+ struct advise_sink *sink, *cursor;
+ struct list *entry;
DWORD timeOut = INFINITE;
- DWORD tmpTimeOut;
MSG msg;
HRESULT hr;
REFERENCE_TIME curTime;
- SystemClockAdviseEntry* it = NULL;
TRACE("(%p): Main Loop\n", This);
@@ -115,31 +99,33 @@ static DWORD WINAPI SystemClockAdviseThread(LPVOID lpParam) {
}
/** First SingleShots Advice: sorted list */
- it = This->pSingleShotAdvise;
- while ((NULL != it) && (it->rtBaseTime + it->rtIntervalTime) <= curTime) {
- SystemClockAdviseEntry* nextit = it->next;
- /** send event ... */
- SetEvent(it->hEvent);
- /** ... and Release it */
- QUARTZ_RemoveAviseEntryFromQueue(This, it);
- heap_free(it);
- it = nextit;
+ LIST_FOR_EACH_ENTRY_SAFE(sink, cursor, &This->single_sinks, struct advise_sink, entry)
+ {
+ if (sink->rtBaseTime + sink->rtIntervalTime > curTime)
+ break;
+
+ SetEvent(sink->hEvent);
+ list_remove(&sink->entry);
+ heap_free(sink);
+ }
+
+ if ((entry = list_head(&This->single_sinks)))
+ {
+ sink = LIST_ENTRY(entry, struct advise_sink, entry);
+ timeOut = (sink->rtBaseTime + sink->rtIntervalTime - curTime) / 10000;
}
- if (NULL != it) timeOut = (DWORD) ((it->rtBaseTime + it->rtIntervalTime) - curTime) / (REFERENCE_TIME)10000;
else timeOut = INFINITE;
/** Now Periodics Advice: semi sorted list (sort cannot be used) */
- for (it = This->pPeriodicAdvise; NULL != it; it = it->next) {
- if (it->rtBaseTime <= curTime) {
- DWORD nPeriods = (DWORD) ((curTime - it->rtBaseTime) / it->rtIntervalTime);
- /** Release the semaphore ... */
- ReleaseSemaphore(it->hEvent, nPeriods, NULL);
- /** ... and refresh time */
- it->rtBaseTime += nPeriods * it->rtIntervalTime;
- /*assert( it->rtBaseTime + it->rtIntervalTime < curTime );*/
+ LIST_FOR_EACH_ENTRY(sink, &This->periodic_sinks, struct advise_sink, entry)
+ {
+ if (sink->rtBaseTime <= curTime)
+ {
+ DWORD periods = (curTime - sink->rtBaseTime) / sink->rtIntervalTime;
+ ReleaseSemaphore(sink->hEvent, periods, NULL);
+ sink->rtBaseTime += periods * sink->rtIntervalTime;
}
- tmpTimeOut = (DWORD) ((it->rtBaseTime + it->rtIntervalTime) - curTime) / (REFERENCE_TIME)10000;
- if (timeOut > tmpTimeOut) timeOut = tmpTimeOut;
+ timeOut = min(timeOut, ((sink->rtBaseTime + sink->rtIntervalTime) - curTime) / 10000);
}
outrefresh:
@@ -263,101 +249,112 @@ static HRESULT WINAPI SystemClockImpl_GetTime(IReferenceClock *iface, REFERENCE_
return hr;
}
-static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock* iface, REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, HEVENT hEvent, DWORD_PTR* pdwAdviseCookie) {
- SystemClockImpl *This = impl_from_IReferenceClock(iface);
- SystemClockAdviseEntry* pEntry = NULL;
+static HRESULT WINAPI SystemClockImpl_AdviseTime(IReferenceClock *iface,
+ REFERENCE_TIME base, REFERENCE_TIME offset, HEVENT event, DWORD_PTR *cookie)
+{
+ SystemClockImpl *clock = impl_from_IReferenceClock(iface);
+ struct advise_sink *sink;
- TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtBaseTime),
- wine_dbgstr_longlong(rtStreamTime), hEvent, pdwAdviseCookie);
+ TRACE("clock %p, base %s, offset %s, event %#lx, cookie %p.\n",
+ clock, wine_dbgstr_longlong(base), wine_dbgstr_longlong(offset), event, cookie);
- if (!hEvent) {
- return E_INVALIDARG;
- }
- if (0 >= rtBaseTime + rtStreamTime) {
- return E_INVALIDARG;
- }
- if (NULL == pdwAdviseCookie) {
- return E_POINTER;
- }
+ if (!event)
+ return E_INVALIDARG;
- if (!(pEntry = heap_alloc_zero(sizeof(*pEntry))))
- return E_OUTOFMEMORY;
+ if (base + offset <= 0)
+ return E_INVALIDARG;
- pEntry->hEvent = (HANDLE) hEvent;
- pEntry->rtBaseTime = rtBaseTime + rtStreamTime;
- pEntry->rtIntervalTime = 0;
+ if (!cookie)
+ return E_POINTER;
- EnterCriticalSection(&This->safe);
- QUARTZ_InsertAviseEntryFromQueue(This, pEntry, &This->pSingleShotAdvise);
- LeaveCriticalSection(&This->safe);
+ if (!(sink = heap_alloc_zero(sizeof(*sink))))
+ return E_OUTOFMEMORY;
- SystemClockPostMessageToAdviseThread(This, ADVISE_ADD_SINGLESHOT);
+ sink->hEvent = (HANDLE)event;
+ sink->rtBaseTime = base + offset;
+ sink->rtIntervalTime = 0;
- *pdwAdviseCookie = (DWORD_PTR) (pEntry);
- return S_OK;
+ EnterCriticalSection(&clock->safe);
+ insert_advise_sink(sink, &clock->single_sinks);
+ LeaveCriticalSection(&clock->safe);
+
+ SystemClockPostMessageToAdviseThread(clock, ADVISE_ADD_SINGLESHOT);
+
+ *cookie = (DWORD_PTR)sink;
+ return S_OK;
}
-static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface, REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, HSEMAPHORE hSemaphore, DWORD_PTR* pdwAdviseCookie) {
- SystemClockImpl *This = impl_from_IReferenceClock(iface);
- SystemClockAdviseEntry* pEntry = NULL;
+static HRESULT WINAPI SystemClockImpl_AdvisePeriodic(IReferenceClock* iface,
+ REFERENCE_TIME start, REFERENCE_TIME period, HSEMAPHORE semaphore, DWORD_PTR *cookie)
+{
+ SystemClockImpl *clock = impl_from_IReferenceClock(iface);
+ struct advise_sink *sink;
- TRACE("(%p, 0x%s, 0x%s, %ld, %p)\n", This, wine_dbgstr_longlong(rtStartTime),
- wine_dbgstr_longlong(rtPeriodTime), hSemaphore, pdwAdviseCookie);
+ TRACE("clock %p, start %s, period %s, semaphore %#lx, cookie %p.\n",
+ clock, wine_dbgstr_longlong(start), wine_dbgstr_longlong(period), semaphore, cookie);
- if (!hSemaphore) {
- return E_INVALIDARG;
- }
- if (0 >= rtStartTime || 0 >= rtPeriodTime) {
- return E_INVALIDARG;
- }
- if (NULL == pdwAdviseCookie) {
- return E_POINTER;
- }
+ if (!semaphore)
+ return E_INVALIDARG;
- if (!(pEntry = heap_alloc_zero(sizeof(*pEntry))))
- return E_OUTOFMEMORY;
+ if (start <= 0 || period <= 0)
+ return E_INVALIDARG;
- pEntry->hEvent = (HANDLE) hSemaphore;
- pEntry->rtBaseTime = rtStartTime;
- pEntry->rtIntervalTime = rtPeriodTime;
+ if (!cookie)
+ return E_POINTER;
- EnterCriticalSection(&This->safe);
- QUARTZ_InsertAviseEntryFromQueue(This, pEntry, &This->pPeriodicAdvise);
- LeaveCriticalSection(&This->safe);
+ if (!(sink = heap_alloc_zero(sizeof(*sink))))
+ return E_OUTOFMEMORY;
- SystemClockPostMessageToAdviseThread(This, ADVISE_ADD_PERIODIC);
+ sink->hEvent = (HANDLE)semaphore;
+ sink->rtBaseTime = start;
+ sink->rtIntervalTime = period;
- *pdwAdviseCookie = (DWORD_PTR) (pEntry);
- return S_OK;
+ EnterCriticalSection(&clock->safe);
+ insert_advise_sink(sink, &clock->periodic_sinks);
+ LeaveCriticalSection(&clock->safe);
+
+ SystemClockPostMessageToAdviseThread(clock, ADVISE_ADD_PERIODIC);
+
+ *cookie = (DWORD_PTR)sink;
+ return S_OK;
}
-static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock* iface, DWORD_PTR dwAdviseCookie) {
- SystemClockImpl *This = impl_from_IReferenceClock(iface);
- SystemClockAdviseEntry* pEntry = NULL;
- SystemClockAdviseEntry* it = NULL;
- HRESULT ret = S_OK;
- TRACE("(%p, %lu)\n", This, dwAdviseCookie);
+static HRESULT WINAPI SystemClockImpl_Unadvise(IReferenceClock *iface, DWORD_PTR cookie)
+{
+ SystemClockImpl *clock = impl_from_IReferenceClock(iface);
+ struct advise_sink *sink;
- pEntry = (SystemClockAdviseEntry*) dwAdviseCookie;
+ TRACE("clock %p, cookie %#lx.\n", clock, cookie);
- EnterCriticalSection(&This->safe);
- for (it = This->pPeriodicAdvise; NULL != it && it != pEntry; it = it->next) ;
- if (it != pEntry) {
- for (it = This->pSingleShotAdvise; NULL != it && it != pEntry; it = it->next) ;
- if (it != pEntry) {
- ret = S_FALSE;
- goto out;
+ EnterCriticalSection(&clock->safe);
+
+ LIST_FOR_EACH_ENTRY(sink, &clock->single_sinks, struct advise_sink, entry)
+ {
+ if (sink == (struct advise_sink *)cookie)
+ {
+ list_remove(&sink->entry);
+ heap_free(sink);
+ SystemClockPostMessageToAdviseThread(clock, ADVISE_REMOVE);
+ LeaveCriticalSection(&clock->safe);
+ return S_OK;
+ }
}
- }
- QUARTZ_RemoveAviseEntryFromQueue(This, pEntry);
- heap_free(pEntry);
+ LIST_FOR_EACH_ENTRY(sink, &clock->periodic_sinks, struct advise_sink, entry)
+ {
+ if (sink == (struct advise_sink *)cookie)
+ {
+ list_remove(&sink->entry);
+ heap_free(sink);
+ SystemClockPostMessageToAdviseThread(clock, ADVISE_REMOVE);
+ LeaveCriticalSection(&clock->safe);
+ return S_OK;
+ }
+ }
- SystemClockPostMessageToAdviseThread(This, ADVISE_REMOVE);
+ LeaveCriticalSection(&clock->safe);
-out:
- LeaveCriticalSection(&This->safe);
- return ret;
+ return S_FALSE;
}
static const IReferenceClockVtbl SystemClock_Vtbl =
@@ -384,7 +381,8 @@ HRESULT QUARTZ_CreateSystemClock(IUnknown *outer, void **out)
}
object->IReferenceClock_iface.lpVtbl = &SystemClock_Vtbl;
-
+ list_init(&object->single_sinks);
+ list_init(&object->periodic_sinks);
InitializeCriticalSection(&object->safe);
object->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SystemClockImpl.safe");
--
2.20.1