[PATCH 1/5] quartz/systemclock: Use the standard linked list implementation.

Zebediah Figura z.figura12 at gmail.com
Thu Mar 14 19:10:57 CDT 2019


Signed-off-by: Zebediah Figura <z.figura12 at 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




More information about the wine-devel mailing list