Index: source/common/umutex.cpp |
diff --git a/source/common/umutex.cpp b/source/common/umutex.cpp |
index 8f552089f7f054ce3521ecbb099cfc873f61f464..0c1fdc8073005b89bdc92dd9feb6513c27757ceb 100644 |
--- a/source/common/umutex.cpp |
+++ b/source/common/umutex.cpp |
@@ -1,7 +1,7 @@ |
/* |
****************************************************************************** |
* |
-* Copyright (C) 1997-2013, International Business Machines |
+* Copyright (C) 1997-2014, International Business Machines |
* Corporation and others. All Rights Reserved. |
* |
****************************************************************************** |
@@ -23,7 +23,6 @@ |
#include "unicode/utypes.h" |
#include "uassert.h" |
#include "cmemory.h" |
-#include "ucln_cmn.h" |
// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. |
@@ -69,7 +68,7 @@ U_NAMESPACE_BEGIN |
U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { |
for (;;) { |
int32_t previousState = InterlockedCompareExchange( |
-#if (U_PLATFORM == U_PF_MINGW) || (U_PLATFORM == U_PF_CYGWIN) |
+#if (U_PLATFORM == U_PF_MINGW) || (U_PLATFORM == U_PF_CYGWIN) || defined(__clang__) |
(LONG volatile *) // this is the type given in the API doc for this function. |
#endif |
&uio.fState, // Destination |
@@ -133,6 +132,63 @@ umtx_unlock(UMutex* mutex) |
LeaveCriticalSection(&mutex->fCS); |
} |
+ |
+U_CAPI void U_EXPORT2 |
+umtx_condBroadcast(UConditionVar *condition) { |
+ // We require that the associated mutex be held by the caller, |
+ // so access to fWaitCount is protected and safe. No other thread can |
+ // call condWait() while we are here. |
+ if (condition->fWaitCount == 0) { |
+ return; |
+ } |
+ ResetEvent(condition->fExitGate); |
+ SetEvent(condition->fEntryGate); |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umtx_condSignal(UConditionVar *condition) { |
+ // Function not implemented. There is no immediate requirement from ICU to have it. |
+ // Once ICU drops support for Windows XP and Server 2003, ICU Condition Variables will be |
+ // changed to be thin wrappers on native Windows CONDITION_VARIABLEs, and this function |
+ // becomes trivial to provide. |
+ U_ASSERT(FALSE); |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umtx_condWait(UConditionVar *condition, UMutex *mutex) { |
+ if (condition->fEntryGate == NULL) { |
+ // Note: because the associated mutex must be locked when calling |
+ // wait, we know that there can not be multiple threads |
+ // running here with the same condition variable. |
+ // Meaning that lazy initialization is safe. |
+ U_ASSERT(condition->fExitGate == NULL); |
+ condition->fEntryGate = CreateEvent(NULL, // Security Attributes |
+ TRUE, // Manual Reset |
+ FALSE, // Initially reset |
+ NULL); // Name. |
+ U_ASSERT(condition->fEntryGate != NULL); |
+ condition->fExitGate = CreateEvent(NULL, TRUE, TRUE, NULL); |
+ U_ASSERT(condition->fExitGate != NULL); |
+ } |
+ |
+ condition->fWaitCount++; |
+ umtx_unlock(mutex); |
+ WaitForSingleObject(condition->fEntryGate, INFINITE); |
+ umtx_lock(mutex); |
+ condition->fWaitCount--; |
+ if (condition->fWaitCount == 0) { |
+ // All threads that were waiting at the entry gate have woken up |
+ // and moved through. Shut the entry gate and open the exit gate. |
+ ResetEvent(condition->fEntryGate); |
+ SetEvent(condition->fExitGate); |
+ } else { |
+ umtx_unlock(mutex); |
+ WaitForSingleObject(condition->fExitGate, INFINITE); |
+ umtx_lock(mutex); |
+ } |
+} |
+ |
+ |
#elif U_PLATFORM_IMPLEMENTS_POSIX |
//------------------------------------------------------------------------------------------- |
@@ -169,6 +225,33 @@ umtx_unlock(UMutex* mutex) |
U_ASSERT(sysErr == 0); |
} |
+ |
+U_CAPI void U_EXPORT2 |
+umtx_condWait(UConditionVar *cond, UMutex *mutex) { |
+ if (mutex == NULL) { |
+ mutex = &globalMutex; |
+ } |
+ int sysErr = pthread_cond_wait(&cond->fCondition, &mutex->fMutex); |
+ (void)sysErr; |
+ U_ASSERT(sysErr == 0); |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umtx_condBroadcast(UConditionVar *cond) { |
+ int sysErr = pthread_cond_broadcast(&cond->fCondition); |
+ (void)sysErr; |
+ U_ASSERT(sysErr == 0); |
+} |
+ |
+U_CAPI void U_EXPORT2 |
+umtx_condSignal(UConditionVar *cond) { |
+ int sysErr = pthread_cond_signal(&cond->fCondition); |
+ (void)sysErr; |
+ U_ASSERT(sysErr == 0); |
+} |
+ |
+ |
+ |
U_NAMESPACE_BEGIN |
static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER; |