You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by da...@apache.org on 2007/07/12 21:29:44 UTC

svn commit: r555730 - in /apr/apr/trunk: include/arch/win32/apr_arch_thread_cond.h locks/win32/thread_cond.c test/testcond.c

Author: davi
Date: Thu Jul 12 12:29:43 2007
New Revision: 555730

URL: http://svn.apache.org/viewvc?view=rev&rev=555730
Log:
Improve WIN32 condition variables fairness by using a generation count. The count
assures that one thread won't steal wakeups from other threads in the queue.

Modified:
    apr/apr/trunk/include/arch/win32/apr_arch_thread_cond.h
    apr/apr/trunk/locks/win32/thread_cond.c
    apr/apr/trunk/test/testcond.c

Modified: apr/apr/trunk/include/arch/win32/apr_arch_thread_cond.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/win32/apr_arch_thread_cond.h?view=diff&rev=555730&r1=555729&r2=555730
==============================================================================
--- apr/apr/trunk/include/arch/win32/apr_arch_thread_cond.h (original)
+++ apr/apr/trunk/include/arch/win32/apr_arch_thread_cond.h Thu Jul 12 12:29:43 2007
@@ -25,6 +25,7 @@
     CRITICAL_SECTION csection;
     unsigned long num_waiting;
     unsigned long num_wake;
+    unsigned long generation;
 };
 
 #endif  /* THREAD_COND_H */

Modified: apr/apr/trunk/locks/win32/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/locks/win32/thread_cond.c?view=diff&rev=555730&r1=555729&r2=555730
==============================================================================
--- apr/apr/trunk/locks/win32/thread_cond.c (original)
+++ apr/apr/trunk/locks/win32/thread_cond.c Thu Jul 12 12:29:43 2007
@@ -67,27 +67,43 @@
 {
     DWORD res;
     apr_status_t rv;
+    unsigned int wake = 0;
+    unsigned long generation;
 
     EnterCriticalSection(&cond->csection);
     cond->num_waiting++;
+    generation = cond->generation;
     LeaveCriticalSection(&cond->csection);
 
     apr_thread_mutex_unlock(mutex);
 
     do {
         res = WaitForSingleObject(cond->semaphore, timeout_ms);
+
         EnterCriticalSection(&cond->csection);
+
         if (cond->num_wake) {
-            cond->num_wake--;
-            rv = APR_SUCCESS;
-            break;
+            if (cond->generation != generation) {
+                cond->num_wake--;
+                cond->num_waiting--;
+                rv = APR_SUCCESS;
+                break;
+            } else {
+                wake = 1;
+            }
         }
         else if (res != WAIT_OBJECT_0) {
             cond->num_waiting--;
             rv = APR_TIMEUP;
             break;
         }
+
         LeaveCriticalSection(&cond->csection);
+
+        if (wake) {
+            wake = 0;
+            ReleaseSemaphore(cond->semaphore, 1, NULL);
+        }
     } while (1);
 
     LeaveCriticalSection(&cond->csection);
@@ -116,10 +132,10 @@
     unsigned int wake = 0;
 
     EnterCriticalSection(&cond->csection);
-    if (cond->num_waiting) {
+    if (cond->num_waiting > cond->num_wake) {
         wake = 1;
         cond->num_wake++;
-        cond->num_waiting--;
+        cond->generation++;
     }
     LeaveCriticalSection(&cond->csection);
 
@@ -135,9 +151,10 @@
     unsigned long num_wake = 0;
 
     EnterCriticalSection(&cond->csection);
-    if (cond->num_waiting) {
-        cond->num_wake += num_wake = cond->num_waiting;
-        cond->num_waiting = 0;
+    if (cond->num_waiting > cond->num_wake) {
+        num_wake = cond->num_waiting - cond->num_wake;
+        cond->num_wake = cond->num_waiting;
+        cond->generation++;
     }
     LeaveCriticalSection(&cond->csection);
 

Modified: apr/apr/trunk/test/testcond.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/test/testcond.c?view=diff&rev=555730&r1=555729&r2=555730
==============================================================================
--- apr/apr/trunk/test/testcond.c (original)
+++ apr/apr/trunk/test/testcond.c Thu Jul 12 12:29:43 2007
@@ -511,20 +511,19 @@
     rv = apr_thread_mutex_lock(box->mutex);
     ABTS_SUCCESS(rv);
 
+    if (state == TOSS)
+        state = PING;
+
     do {
+        rv = apr_thread_cond_signal(box->cond);
+        ABTS_SUCCESS(rv);
+
         state = PONG;
 
-        rv = apr_thread_cond_signal(box->cond);
+        rv = apr_thread_cond_wait(box->cond, box->mutex);
         ABTS_SUCCESS(rv);
 
-        do {
-            rv = apr_thread_cond_wait(box->cond, box->mutex);
-            ABTS_SUCCESS(rv);
-            if (state == OVER) {
-                break;
-            }
-            ABTS_INT_EQUAL(tc, 1, (state == PING));
-        } while (state == PONG);
+        ABTS_TRUE(tc, state == PING || state == OVER);
     } while (state != OVER);
 
     rv = apr_thread_mutex_unlock(box->mutex);
@@ -542,20 +541,19 @@
     rv = apr_thread_mutex_lock(box->mutex);
     ABTS_SUCCESS(rv);
 
+    if (state == TOSS)
+        state = PONG;
+
     do {
+        rv = apr_thread_cond_signal(box->cond);
+        ABTS_SUCCESS(rv);
+
         state = PING;
 
-        rv = apr_thread_cond_signal(box->cond);
+        rv = apr_thread_cond_wait(box->cond, box->mutex);
         ABTS_SUCCESS(rv);
 
-        do {
-            rv = apr_thread_cond_wait(box->cond, box->mutex);
-            ABTS_SUCCESS(rv);
-            if (state == OVER) {
-                break;
-            }
-            ABTS_INT_EQUAL(tc, 1, (state == PONG));
-        } while (state == PING);
+        ABTS_TRUE(tc, state == PONG || state == OVER);
     } while (state != OVER);
 
     rv = apr_thread_mutex_unlock(box->mutex);