X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/57a6839dcb3bba09e8228b822b290604668416fe..cecc3f9394f261e71def48cf396d137687dbd0a7:/icuSources/common/umutex.cpp diff --git a/icuSources/common/umutex.cpp b/icuSources/common/umutex.cpp index 8f552089..29dbc90e 100644 --- a/icuSources/common/umutex.cpp +++ b/icuSources/common/umutex.cpp @@ -1,7 +1,9 @@ +// © 2016 and later: Unicode, Inc. and others. +// License & terms of use: http://www.unicode.org/copyright.html /* ****************************************************************************** * -* Copyright (C) 1997-2013, International Business Machines +* Copyright (C) 1997-2016, International Business Machines * Corporation and others. All Rights Reserved. * ****************************************************************************** @@ -23,7 +25,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. @@ -38,16 +39,7 @@ static UMutex globalMutex = U_MUTEX_INITIALIZER; // Build time user mutex hook: #include "U_USER_MUTEX_CPP" #include U_MUTEX_XSTR(U_USER_MUTEX_CPP) -#elif U_PLATFORM_HAS_WIN32_API - -//------------------------------------------------------------------------------------------- -// -// Windows Specific Definitions -// -// Note: Cygwin (and possibly others) have both WIN32 and POSIX. -// Prefer Win32 in these cases. (Win32 comes ahead in the #if chain) -// -//------------------------------------------------------------------------------------------- +#elif U_PLATFORM_USES_ONLY_WIN32_API #if defined U_NO_PLATFORM_ATOMICS #error ICU on Win32 requires support for low level atomic operations. @@ -69,10 +61,8 @@ 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) - (LONG volatile *) // this is the type given in the API doc for this function. -#endif - &uio.fState, // Destination + (LONG volatile *) // this is the type given in the API doc for this function. + &uio.fState, // Destination 1, // Exchange Value 0); // Compare value @@ -97,11 +87,6 @@ U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { // This function is called by the thread that ran an initialization function, // just after completing the function. -// -// success: True: the inialization succeeded. No further calls to the init -// function will be made. -// False: the initializtion failed. The next call to umtx_initOnce() -// will retry the initialization. U_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) { umtx_storeRelease(uio.fState, 2); @@ -133,6 +118,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 +211,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; @@ -266,8 +335,8 @@ umtx_atomic_dec(u_atomic_int32_t *p) { U_COMMON_API int32_t U_EXPORT2 umtx_loadAcquire(u_atomic_int32_t &var) { - int32_t val = var; umtx_lock(&gIncDecMutex); + int32_t val = var; umtx_unlock(&gIncDecMutex); return val; } @@ -275,8 +344,8 @@ umtx_loadAcquire(u_atomic_int32_t &var) { U_COMMON_API void U_EXPORT2 umtx_storeRelease(u_atomic_int32_t &var, int32_t val) { umtx_lock(&gIncDecMutex); - umtx_unlock(&gIncDecMutex); var = val; + umtx_unlock(&gIncDecMutex); } U_NAMESPACE_END