[Freeswitch-svn] [commit] r10334 - in freeswitch/trunk: libs/apr/include/arch/win32 libs/apr/locks/win32 src

FreeSWITCH SVN mikej at freeswitch.org
Tue Nov 11 10:35:49 PST 2008


Author: mikej
Date: Tue Nov 11 13:35:48 2008
New Revision: 10334

Log:
pull back change from apr 1.3.0

" *) Rework the WIN32 CV code to signal the condition only if one or
     more threads are blocked on the condition variable. If no threads
     are waiting on the condition variable, nothing happens. The change
     also eliminates the thundering-herd problem of the manual-reset
     event, which (theoretically) wakes up all threads waiting on. Now
     the behavior of the CV's should be the same on Unix and win32
     platforms. PR 42305.  [Davi Arnaut]
"

Modified:
   freeswitch/trunk/libs/apr/include/arch/win32/apr_arch_thread_cond.h
   freeswitch/trunk/libs/apr/locks/win32/thread_cond.c
   freeswitch/trunk/src/switch_time.c

Modified: freeswitch/trunk/libs/apr/include/arch/win32/apr_arch_thread_cond.h
==============================================================================
--- freeswitch/trunk/libs/apr/include/arch/win32/apr_arch_thread_cond.h	(original)
+++ freeswitch/trunk/libs/apr/include/arch/win32/apr_arch_thread_cond.h	Tue Nov 11 13:35:48 2008
@@ -21,10 +21,11 @@
 
 struct apr_thread_cond_t {
     apr_pool_t *pool;
-    HANDLE event;
-    int signal_all;
-    int num_waiting;
-    int signalled;
+    HANDLE semaphore;
+    CRITICAL_SECTION csection;
+    unsigned long num_waiting;
+    unsigned long num_wake;
+    unsigned long generation;
 };
 
 #endif  /* THREAD_COND_H */

Modified: freeswitch/trunk/libs/apr/locks/win32/thread_cond.c
==============================================================================
--- freeswitch/trunk/libs/apr/locks/win32/thread_cond.c	(original)
+++ freeswitch/trunk/libs/apr/locks/win32/thread_cond.c	Tue Nov 11 13:35:48 2008
@@ -18,67 +18,98 @@
 #include "apr_private.h"
 #include "apr_general.h"
 #include "apr_strings.h"
-#include "win32/apr_arch_thread_mutex.h"
-#include "win32/apr_arch_thread_cond.h"
+#include "apr_arch_thread_mutex.h"
+#include "apr_arch_thread_cond.h"
 #include "apr_portable.h"
 
+#include <limits.h>
+
 static apr_status_t thread_cond_cleanup(void *data)
 {
     apr_thread_cond_t *cond = data;
-    CloseHandle(cond->event);
+    CloseHandle(cond->semaphore);
+    DeleteCriticalSection(&cond->csection);
     return APR_SUCCESS;
 }
 
 APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
                                                  apr_pool_t *pool)
 {
-    *cond = apr_palloc(pool, sizeof(**cond));
-    (*cond)->pool = pool;
-    (*cond)->event = CreateEvent(NULL, TRUE, FALSE, NULL);
-    (*cond)->signal_all = 0;
-    (*cond)->num_waiting = 0;
+    apr_thread_cond_t *cv;
+
+    cv = apr_pcalloc(pool, sizeof(**cond));
+    if (cv == NULL) {
+        return APR_ENOMEM;
+    }
+
+    cv->semaphore = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+    if (cv->semaphore == NULL) {
+        return apr_get_os_error();
+    }
 
-	apr_pool_cleanup_register(pool, *cond, thread_cond_cleanup,
-                          apr_pool_cleanup_null);
+    *cond = cv;
+    cv->pool = pool;
+    InitializeCriticalSection(&cv->csection);
+    apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup,
+                              apr_pool_cleanup_null);
 
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
+{
+    return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
+}
+
 static APR_INLINE apr_status_t _thread_cond_timedwait(apr_thread_cond_t *cond,
                                                       apr_thread_mutex_t *mutex,
                                                       DWORD timeout_ms )
 {
     DWORD res;
-
-    while (1) {
-        cond->num_waiting++;
-
-        apr_thread_mutex_unlock(mutex);
-        res = WaitForSingleObject(cond->event, timeout_ms);
-        apr_thread_mutex_lock(mutex);
-        cond->num_waiting--;
-        if (res != WAIT_OBJECT_0) {
-            apr_status_t rv = apr_get_os_error();
-            if (res == WAIT_TIMEOUT) {
-                return APR_TIMEUP;
+    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) {
+            if (cond->generation != generation) {
+                cond->num_wake--;
+                cond->num_waiting--;
+                rv = APR_SUCCESS;
+                break;
+            } else {
+                wake = 1;
             }
-            return apr_get_os_error();
         }
-        if (cond->signal_all) {
-            if (cond->num_waiting == 0) {
-                cond->signal_all = 0;
-                cond->signalled = 0;
-                ResetEvent(cond->event);
-            }
+        else if (res != WAIT_OBJECT_0) {
+            cond->num_waiting--;
+            rv = APR_TIMEUP;
             break;
         }
-        else if (cond->signalled) {
-            cond->signalled = 0;
-            ResetEvent(cond->event);
-            break;
+
+        LeaveCriticalSection(&cond->csection);
+
+        if (wake) {
+            wake = 0;
+            ReleaseSemaphore(cond->semaphore, 1, NULL);
         }
-    }
-    return APR_SUCCESS;
+    } while (1);
+
+    LeaveCriticalSection(&cond->csection);
+    apr_thread_mutex_lock(mutex);
+
+    return rv;
 }
 
 APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
@@ -98,35 +129,40 @@
 
 APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
 {
-    apr_status_t rv = APR_SUCCESS;
-    DWORD res;
+    unsigned int wake = 0;
 
-    cond->signalled = 1;
-    res = SetEvent(cond->event);
-    if (res == 0) {
-        rv = apr_get_os_error();
+    EnterCriticalSection(&cond->csection);
+    if (cond->num_waiting > cond->num_wake) {
+        wake = 1;
+        cond->num_wake++;
+        cond->generation++;
     }
-    return rv;
+    LeaveCriticalSection(&cond->csection);
+
+    if (wake) {
+        ReleaseSemaphore(cond->semaphore, 1, NULL);
+    }
+
+    return APR_SUCCESS;
 }
 
 APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
 {
-    apr_status_t rv = APR_SUCCESS;
-    DWORD res;
+    unsigned long num_wake = 0;
 
-    cond->signalled = 1;
-    cond->signal_all = 1;
-    res = SetEvent(cond->event);
-    if (res == 0) {
-        rv = apr_get_os_error();
+    EnterCriticalSection(&cond->csection);
+    if (cond->num_waiting > cond->num_wake) {
+        num_wake = cond->num_waiting - cond->num_wake;
+        cond->num_wake = cond->num_waiting;
+        cond->generation++;
     }
-    return rv;
-}
+    LeaveCriticalSection(&cond->csection);
 
-APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
-{
-    return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
+    if (num_wake) {
+        ReleaseSemaphore(cond->semaphore, num_wake, NULL);
+    }
+
+    return APR_SUCCESS;
 }
 
 APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
-

Modified: freeswitch/trunk/src/switch_time.c
==============================================================================
--- freeswitch/trunk/src/switch_time.c	(original)
+++ freeswitch/trunk/src/switch_time.c	Tue Nov 11 13:35:48 2008
@@ -408,9 +408,7 @@
 	switch_mutex_init(&TIMER_MATRIX[1].mutex, SWITCH_MUTEX_NESTED, module_pool);
 	switch_thread_cond_create(&TIMER_MATRIX[1].cond, module_pool);
 	
-#ifndef WIN32
 	globals.use_cond_yield = globals.RUNNING == 1;
-#endif	
 
 	while (globals.RUNNING == 1) {
 		runtime.reference += STEP_MIC;



More information about the Freeswitch-svn mailing list