You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by bj...@apache.org on 2010/04/03 14:28:58 UTC

svn commit: r930508 - in /apr/apr/trunk: include/arch/os2/apr_arch_thread_cond.h locks/os2/thread_cond.c

Author: bjh
Date: Sat Apr  3 12:28:52 2010
New Revision: 930508

URL: http://svn.apache.org/viewvc?rev=930508&view=rev
Log:
OS/2: Add an implementation of condition variables, derived from the Win32
implementation.

Modified:
    apr/apr/trunk/include/arch/os2/apr_arch_thread_cond.h
    apr/apr/trunk/locks/os2/thread_cond.c

Modified: apr/apr/trunk/include/arch/os2/apr_arch_thread_cond.h
URL: http://svn.apache.org/viewvc/apr/apr/trunk/include/arch/os2/apr_arch_thread_cond.h?rev=930508&r1=930507&r2=930508&view=diff
==============================================================================
--- apr/apr/trunk/include/arch/os2/apr_arch_thread_cond.h (original)
+++ apr/apr/trunk/include/arch/os2/apr_arch_thread_cond.h Sat Apr  3 12:28:52 2010
@@ -22,6 +22,11 @@
 
 struct apr_thread_cond_t {
     apr_pool_t *pool;
+    HEV semaphore;
+    HMTX mutex;
+    unsigned long num_waiting;
+    unsigned long num_wake;
+    unsigned long generation;
 };
 
 #endif  /* THREAD_COND_H */

Modified: apr/apr/trunk/locks/os2/thread_cond.c
URL: http://svn.apache.org/viewvc/apr/apr/trunk/locks/os2/thread_cond.c?rev=930508&r1=930507&r2=930508&view=diff
==============================================================================
--- apr/apr/trunk/locks/os2/thread_cond.c (original)
+++ apr/apr/trunk/locks/os2/thread_cond.c Sat Apr  3 12:28:52 2010
@@ -23,38 +23,171 @@
 #include "apr_arch_file_io.h"
 #include <string.h>
 
+#ifndef DCE_POSTONE
+#define DCE_POSTONE   0x0800 // Post one flag
+#endif
+
+static apr_status_t thread_cond_cleanup(void *data)
+{
+    apr_thread_cond_t *cv = data;
+
+    if (cv->semaphore) {
+        DosCloseEventSem(cv->semaphore);
+    }
+
+    if (cv->mutex) {
+        DosCloseMutexSem(cv->mutex);
+    }
+
+    return APR_SUCCESS;
+}
+
+
+
 APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
                                                  apr_pool_t *pool)
 {
-    return APR_ENOTIMPL;
+    int rc;
+    apr_thread_cond_t *cv;
+
+    cv = apr_pcalloc(pool, sizeof(**cond));
+    rc = DosCreateEventSem(NULL, &cv->semaphore, DCE_POSTONE, FALSE);
+
+    if (rc == 0) {
+        rc = DosCreateMutexSem(NULL, &cv->mutex, 0, FALSE);
+    }
+
+    *cond = cv;
+    cv->pool = pool;
+    apr_pool_cleanup_register(cv->pool, cv, thread_cond_cleanup,
+                              apr_pool_cleanup_null);
+
+    return APR_FROM_OS_ERROR(rc);
+}
+
+
+
+static apr_status_t thread_cond_timedwait(apr_thread_cond_t *cond,
+                                          apr_thread_mutex_t *mutex,
+                                          ULONG timeout_ms )
+{
+    ULONG rc;
+    apr_status_t rv = APR_SUCCESS;
+    int wake = FALSE;
+    unsigned long generation;
+
+    DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+    cond->num_waiting++;
+    generation = cond->generation;
+    DosReleaseMutexSem(cond->mutex);
+
+    apr_thread_mutex_unlock(mutex);
+
+    do {
+        rc = DosWaitEventSem(cond->semaphore, timeout_ms);
+
+        DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+        if (cond->num_wake) {
+            if (cond->generation != generation) {
+                cond->num_wake--;
+                cond->num_waiting--;
+                rv = APR_SUCCESS;
+                break;
+            } else {
+                wake = TRUE;
+            }
+        }
+        else if (rc != 0) {
+            cond->num_waiting--;
+            rv = APR_TIMEUP;
+            break;
+        }
+
+        DosReleaseMutexSem(cond->mutex);
+
+        if (wake) {
+            wake = FALSE;
+            DosPostEventSem(cond->semaphore);
+        }
+    } while (1);
+
+    DosReleaseMutexSem(cond->mutex);
+    apr_thread_mutex_lock(mutex);
+    return rv;
 }
 
+
+
 APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
                                                apr_thread_mutex_t *mutex)
 {
-    return APR_ENOTIMPL;
+    return thread_cond_timedwait(cond, mutex, SEM_INDEFINITE_WAIT);
 }
 
+
+
 APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond,
                                                     apr_thread_mutex_t *mutex,
-                                                    apr_interval_time_t timeout){
-    return APR_ENOTIMPL;
+                                                    apr_interval_time_t timeout)
+{
+    ULONG timeout_ms = apr_time_as_msec(timeout);
+    return thread_cond_timedwait(cond, mutex, timeout_ms);
 }
 
+
+
 APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond)
 {
-    return APR_ENOTIMPL;
+    int wake = FALSE;
+
+    DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+    if (cond->num_waiting > cond->num_wake) {
+        wake = TRUE;
+        cond->num_wake++;
+        cond->generation++;
+    }
+
+    DosReleaseMutexSem(cond->mutex);
+
+    if (wake) {
+        DosPostEventSem(cond->semaphore);
+    }
+
+    return APR_SUCCESS;
 }
 
+
+
 APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond)
 {
-    return APR_ENOTIMPL;
+    unsigned long num_wake = 0;
+
+    DosRequestMutexSem(cond->mutex, SEM_INDEFINITE_WAIT);
+
+    if (cond->num_waiting > cond->num_wake) {
+        num_wake = cond->num_waiting - cond->num_wake;
+        cond->num_wake = cond->num_waiting;
+        cond->generation++;
+    }
+
+    DosReleaseMutexSem(cond->mutex);
+
+    for (; num_wake; num_wake--) {
+        DosPostEventSem(cond->semaphore);
+    }
+
+    return APR_SUCCESS;
 }
 
+
+
 APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond)
 {
-    return APR_ENOTIMPL;
+    return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup);
 }
 
-APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)
 
+
+APR_POOL_IMPLEMENT_ACCESSOR(thread_cond)