]> granicus.if.org Git - icu/commitdiff
ICU-10182 Build Time mutexes, merge from development branch.
authorAndy Heninger <andy.heninger@gmail.com>
Fri, 30 Aug 2013 01:23:42 +0000 (01:23 +0000)
committerAndy Heninger <andy.heninger@gmail.com>
Fri, 30 Aug 2013 01:23:42 +0000 (01:23 +0000)
X-SVN-Rev: 34139

icu4c/source/common/rbbidata.h
icu4c/source/common/umutex.cpp
icu4c/source/common/umutex.h
icu4c/source/common/unistr.cpp
icu4c/source/i18n/uregex.cpp
icu4c/source/i18n/uspoof_impl.h

index 5c48399645fbfc6ad9b89f785c408d0ebc0a3c2e..78a4ac762c88fd13dddf496d449de8de9cb718c2 100644 (file)
@@ -181,7 +181,7 @@ public:
     UTrie               fTrie;
 
 private:
-    atomic_int32_t      fRefCount;
+    u_atomic_int32_t    fRefCount;
     UDataMemory        *fUDataMem;
     UnicodeString       fRuleString;
     UBool               fDontFreeData;
index 18ccf361bb36e504c29fb78c6b2e21658c60e2da..5d65a8e7c73ad60c8bf702b31808f66c46201ee1 100644 (file)
@@ -33,7 +33,11 @@ static UMutex   globalMutex = U_MUTEX_INITIALIZER;
  * platform independent set of mutex operations.  For internal ICU use only.
  */
 
-#if U_PLATFORM_HAS_WIN32_API
+#if defined(U_USER_MUTEX_CPP)
+// Build time user mutex hook: #include "U_USER_MUTEX_CPP"
+#include U_MUTEX_XSTR(U_USER_MUTEX_CPP)
+
+#elif U_PLATFORM_HAS_WIN32_API
 
 //-------------------------------------------------------------------------------------------
 //
@@ -96,9 +100,8 @@ U_CAPI UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) {
 //            False: the initializtion failed. The next call to umtx_initOnce()
 //                   will retry the initialization.
 
-U_CAPI void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio, UBool success) {
-    int32_t nextState = success? 2: 0;
-    umtx_storeRelease(uio.fState, nextState);
+U_CAPI void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) {
+    umtx_storeRelease(uio.fState, 2);
 }
 
 
@@ -180,57 +183,34 @@ UBool umtx_initImplPreInit(UInitOnce &uio) {
     if (state == 0) {
         umtx_storeRelease(uio.fState, 1);
         pthread_mutex_unlock(&initMutex);
-        return true;   // Caller will next call the init function.
-    } else if (state == 2) {
-        // Another thread already completed the initialization, in
-        //   a race with this thread. We can simply return FALSE, indicating no
-        //   further action is needed by the caller.
-        pthread_mutex_unlock(&initMutex);
-        return FALSE;
+        return TRUE;   // Caller will next call the init function.
     } else {
-        // Another thread is currently running the initialization.
-        // Wait until it completes.
-        U_ASSERT(state == 1);
         while (uio.fState == 1) {
+            // Another thread is currently running the initialization.
+            // Wait until it completes.
             pthread_cond_wait(&initCondition, &initMutex);
         }
-        UBool returnVal = uio.fState == 0;
-        if (returnVal) {
-            // Initialization that was running in another thread failed.
-            // We will retry it in this thread.
-            // (This is only used by SimpleSingleton)
-            umtx_storeRelease(uio.fState, 1);
-        }
         pthread_mutex_unlock(&initMutex);
-        return returnVal;
+        U_ASSERT(uio.fState == 2);
+        return FALSE;
     }
 }
 
+        
+
 // This function is called by the thread that ran an initialization function,
 // just after completing the function.
 //   Some threads may be waiting on the condition, requiring the broadcast wakeup.
 //   Some threads may be racing to test the fState variable outside of the mutex,
 //   requiring the use of store/release when changing its value.
-//
-//   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.
 
-void umtx_initImplPostInit(UInitOnce &uio, UBool success) {
-    int32_t nextState = success? 2: 0;
+void umtx_initImplPostInit(UInitOnce &uio) {
     pthread_mutex_lock(&initMutex);
-    umtx_storeRelease(uio.fState, nextState);
+    umtx_storeRelease(uio.fState, 2);
     pthread_cond_broadcast(&initCondition);
     pthread_mutex_unlock(&initMutex);
 }
 
-
-void umtx_initOnceReset(UInitOnce &uio) {
-    // Not a thread safe function, we can use an ordinary assignment.
-    uio.fState = 0;
-}
-
 // End of POSIX specific umutex implementation.
 
 #else  // Platform #define chain.
@@ -254,7 +234,7 @@ void umtx_initOnceReset(UInitOnce &uio) {
 static UMutex   gIncDecMutex = U_MUTEX_INITIALIZER;
 
 U_INTERNAL int32_t U_EXPORT2
-umtx_atomic_inc(int32_t *p)  {
+umtx_atomic_inc(u_atomic_int32_t *p)  {
     int32_t retVal;
     umtx_lock(&gIncDecMutex);
     retVal = ++(*p);
@@ -264,7 +244,7 @@ umtx_atomic_inc(int32_t *p)  {
 
 
 U_INTERNAL int32_t U_EXPORT2
-umtx_atomic_dec(int32_t *p) {
+umtx_atomic_dec(u_atomic_int32_t *p) {
     int32_t retVal;
     umtx_lock(&gIncDecMutex);
     retVal = --(*p);
@@ -273,7 +253,7 @@ umtx_atomic_dec(int32_t *p) {
 }
 
 U_INTERNAL int32_t U_EXPORT2
-umtx_loadAcquire(atomic_int32_t &var) {
+umtx_loadAcquire(u_atomic_int32_t &var) {
     int32_t val = var;
     umtx_lock(&gIncDecMutex);
     umtx_unlock(&gIncDecMutex);
@@ -281,7 +261,7 @@ umtx_loadAcquire(atomic_int32_t &var) {
 }
 
 U_INTERNAL void U_EXPORT2
-umtx_storeRelease(atomic_int32_t &var, int32_t val) {
+umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
     umtx_lock(&gIncDecMutex);
     umtx_unlock(&gIncDecMutex);
     var = val;
index 7f1b44bad9a648e2e326b1b43fab0f618e8defc0..dbbe683fed4d1946af2e4697d5493786b9a58dcb 100644 (file)
@@ -28,6 +28,9 @@
 struct UMutex;
 struct UInitOnce;
 
+// Stringify macros, to allow #include of user supplied atomic & mutex files.
+#define U_MUTEX_STR(s) #s
+#define U_MUTEX_XSTR(s) U_MUTEX_STR(s)
 
 /****************************************************************************
  *
@@ -35,28 +38,31 @@ struct UInitOnce;
  *      Compiler dependent. Not operating system dependent.
  *
  ****************************************************************************/
-#if U_HAVE_STD_ATOMICS
+#if defined (U_USER_ATOMICS_H)
+#include U_MUTEX_XSTR(U_USER_ATOMICS_H)
+
+#elif U_HAVE_STD_ATOMICS
 
 //  C++11 atomics are available.
 
 #include <atomic>
 
-typedef std::atomic<int32_t> atomic_int32_t;
+typedef std::atomic<int32_t> u_atomic_int32_t;
 #define ATOMIC_INT32_T_INITIALIZER(val) ATOMIC_VAR_INIT(val)
 
-inline int32_t umtx_loadAcquire(atomic_int32_t &var) {
+inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
     return var.load(std::memory_order_acquire);
 }
 
-inline void umtx_storeRelease(atomic_int32_t &var, int32_t val) {
+inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
     var.store(val, std::memory_order_release);
 }
 
-inline int32_t umtx_atomic_inc(atomic_int32_t *var) {
+inline int32_t umtx_atomic_inc(u_atomic_int32_t *var) {
     return var->fetch_add(1) + 1;
 }
 
-inline int32_t umtx_atomic_dec(atomic_int32_t *var) {
+inline int32_t umtx_atomic_dec(u_atomic_int32_t *var) {
     return var->fetch_sub(1) - 1;
 }
 
@@ -82,23 +88,23 @@ inline int32_t umtx_atomic_dec(atomic_int32_t *var) {
 # endif
 # include <windows.h>
 
-typedef volatile LONG atomic_int32_t;
+typedef volatile LONG u_atomic_int32_t;
 #define ATOMIC_INT32_T_INITIALIZER(val) val
 
-inline int32_t umtx_loadAcquire(atomic_int32_t &var) {
+inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
     return InterlockedCompareExchange(&var, 0, 0);
 }
 
-inline void umtx_storeRelease(atomic_int32_t &var, int32_t val) {
+inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
     InterlockedExchange(&var, val);
 }
 
 
-inline int32_t umtx_atomic_inc(atomic_int32_t *var) {
+inline int32_t umtx_atomic_inc(u_atomic_int32_t *var) {
     return InterlockedIncrement(var);
 }
 
-inline int32_t umtx_atomic_dec(atomic_int32_t *var) {
+inline int32_t umtx_atomic_dec(u_atomic_int32_t *var) {
     return InterlockedDecrement(var);
 }
 
@@ -107,25 +113,25 @@ inline int32_t umtx_atomic_dec(atomic_int32_t *var) {
 /*
  * gcc atomic ops. These are available on several other compilers as well.
  */
-typedef int32_t atomic_int32_t;
+typedef int32_t u_atomic_int32_t;
 #define ATOMIC_INT32_T_INITIALIZER(val) val
 
-inline int32_t umtx_loadAcquire(atomic_int32_t &var) {
+inline int32_t umtx_loadAcquire(u_atomic_int32_t &var) {
     int32_t val = var;
     __sync_synchronize();
     return val;
 }
 
-inline void umtx_storeRelease(atomic_int32_t &var, int32_t val) {
+inline void umtx_storeRelease(u_atomic_int32_t &var, int32_t val) {
     __sync_synchronize();
     var = val;
 }
 
-inline int32_t umtx_atomic_inc(atomic_int32_t *p)  {
+inline int32_t umtx_atomic_inc(u_atomic_int32_t *p)  {
    return __sync_add_and_fetch(p, 1);
 }
 
-inline int32_t umtx_atomic_dec(atomic_int32_t *p)  {
+inline int32_t umtx_atomic_dec(u_atomic_int32_t *p)  {
    return __sync_sub_and_fetch(p, 1);
 }
 
@@ -138,16 +144,16 @@ inline int32_t umtx_atomic_dec(atomic_int32_t *p)  {
 
 #define U_NO_PLATFORM_ATOMICS
 
-typedef int32_t atomic_int32_t;
+typedef int32_t u_atomic_int32_t;
 #define ATOMIC_INT32_T_INITIALIZER(val) val
 
-U_INTERNAL int32_t U_EXPORT2 umtx_loadAcquire(atomic_int32_t &var);
+U_INTERNAL int32_t U_EXPORT2 umtx_loadAcquire(u_atomic_int32_t &var);
 
-U_INTERNAL void U_EXPORT2 umtx_storeRelease(atomic_int32_t &var, int32_t val);
+U_INTERNAL void U_EXPORT2 umtx_storeRelease(u_atomic_int32_t &var, int32_t val);
 
-U_INTERNAL int32_t U_EXPORT2 umtx_atomic_inc(atomic_int32_t *p);
+U_INTERNAL int32_t U_EXPORT2 umtx_atomic_inc(u_atomic_int32_t *p);
 
-U_INTERNAL int32_t U_EXPORT2 umtx_atomic_dec(atomic_int32_t *p);
+U_INTERNAL int32_t U_EXPORT2 umtx_atomic_dec(u_atomic_int32_t *p);
 
 #endif  /* Low Level Atomic Ops Platfrom Chain */
 
@@ -161,9 +167,9 @@ U_INTERNAL int32_t U_EXPORT2 umtx_atomic_dec(atomic_int32_t *p);
  *************************************************************************************************/
 
 struct UInitOnce {
-    atomic_int32_t   fState;
+    u_atomic_int32_t   fState;
     UErrorCode       fErrCode;
-    void reset() {fState = 0; fState=0;};
+    void reset() {fState = 0;};
     UBool isReset() {return umtx_loadAcquire(fState) == 0;};
 // Note: isReset() is used by service registration code.
 //                 Thread safety of this usage needs review.
@@ -173,7 +179,7 @@ struct UInitOnce {
 
 
 U_CAPI UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &);
-U_CAPI void  U_EXPORT2 umtx_initImplPostInit(UInitOnce &, UBool success);
+U_CAPI void  U_EXPORT2 umtx_initImplPostInit(UInitOnce &);
 
 template<class T> void umtx_initOnce(UInitOnce &uio, T *obj, void (T::*fp)()) {
     if (umtx_loadAcquire(uio.fState) == 2) {
@@ -181,7 +187,7 @@ template<class T> void umtx_initOnce(UInitOnce &uio, T *obj, void (T::*fp)()) {
     }
     if (umtx_initImplPreInit(uio)) {
         (obj->*fp)();
-        umtx_initImplPostInit(uio, TRUE);
+        umtx_initImplPostInit(uio);
     }
 }
 
@@ -194,7 +200,7 @@ inline void umtx_initOnce(UInitOnce &uio, void (*fp)()) {
     }
     if (umtx_initImplPreInit(uio)) {
         (*fp)();
-        umtx_initImplPostInit(uio, TRUE);
+        umtx_initImplPostInit(uio);
     }
 }
 
@@ -208,7 +214,7 @@ inline void umtx_initOnce(UInitOnce &uio, void (*fp)(UErrorCode &), UErrorCode &
         // We run the initialization.
         (*fp)(errCode);
         uio.fErrCode = errCode;
-        umtx_initImplPostInit(uio, TRUE);
+        umtx_initImplPostInit(uio);
     } else {
         // Someone else already ran the initialization.
         if (U_FAILURE(uio.fErrCode)) {
@@ -225,7 +231,7 @@ template<class T> void umtx_initOnce(UInitOnce &uio, void (*fp)(T), T context) {
     }
     if (umtx_initImplPreInit(uio)) {
         (*fp)(context);
-        umtx_initImplPostInit(uio, TRUE);
+        umtx_initImplPostInit(uio);
     }
 }
 
@@ -239,7 +245,7 @@ template<class T> void umtx_initOnce(UInitOnce &uio, void (*fp)(T, UErrorCode &)
         // We run the initialization.
         (*fp)(context, errCode);
         uio.fErrCode = errCode;
-        umtx_initImplPostInit(uio, TRUE);
+        umtx_initImplPostInit(uio);
     } else {
         // Someone else already ran the initialization.
         if (U_FAILURE(uio.fErrCode)) {
@@ -259,7 +265,11 @@ template<class T> void umtx_initOnce(UInitOnce &uio, void (*fp)(T, UErrorCode &)
  *
  *************************************************************************************************/
 
-#if U_PLATFORM_HAS_WIN32_API
+#if defined(U_USER_MUTEX_H)
+// #inlcude "U_USER_MUTEX_H"
+#include U_MUTEX_XSTR(U_USER_MUTEX_H)
+
+#elif U_PLATFORM_HAS_WIN32_API
 
 /* Windows Definitions.
  *    Windows comes first in the platform chain.
index f52550beca987ba7d69d0d3df93cdcb34dfbbf96..b1c24769a01e2c082a90764947058682ba348c75 100644 (file)
@@ -118,11 +118,11 @@ operator+ (const UnicodeString &s1, const UnicodeString &s2) {
 
 void
 UnicodeString::addRef()
-{  umtx_atomic_inc((atomic_int32_t *)fUnion.fFields.fArray - 1);}
+{  umtx_atomic_inc((u_atomic_int32_t *)fUnion.fFields.fArray - 1);}
 
 int32_t
 UnicodeString::removeRef()
-{ return umtx_atomic_dec((atomic_int32_t *)fUnion.fFields.fArray - 1);}
+{ return umtx_atomic_dec((u_atomic_int32_t *)fUnion.fFields.fArray - 1);}
 
 int32_t
 UnicodeString::refCount() const 
@@ -1679,10 +1679,10 @@ UnicodeString::cloneArrayIfNeeded(int32_t newCapacity,
       // release the old array
       if(flags & kRefCounted) {
         // the array is refCounted; decrement and release if 0
-        atomic_int32_t *pRefCount = ((atomic_int32_t *)oldArray - 1);
+        u_atomic_int32_t *pRefCount = ((u_atomic_int32_t *)oldArray - 1);
         if(umtx_atomic_dec(pRefCount) == 0) {
           if(pBufferToDelete == 0) {
-              // Note: cast to (void *) is needed with MSVC, where atomic_int32_t
+              // Note: cast to (void *) is needed with MSVC, where u_atomic_int32_t
               // is defined as volatile. (Volatile has useful non-standard behavior
               //   with this compiler.)
             uprv_free((void *)pRefCount);
index 9763aac1e95ba84b37c675e90b365d2644fb5a4d..6e995b556debb4e60838a95699c6b02e2201ed4d 100644 (file)
@@ -35,7 +35,7 @@ public:
     ~RegularExpression();
     int32_t           fMagic;
     RegexPattern     *fPat;
-    atomic_int32_t   *fPatRefCount;
+    u_atomic_int32_t *fPatRefCount;
     UChar            *fPatString;
     int32_t           fPatStringLen;
     RegexMatcher     *fMatcher;
@@ -123,7 +123,7 @@ uregex_open( const  UChar          *pattern,
     }
 
     RegularExpression  *re     = new RegularExpression;
-    atomic_int32_t     *refC   = (atomic_int32_t *)uprv_malloc(sizeof(int32_t));
+    u_atomic_int32_t   *refC   = (u_atomic_int32_t *)uprv_malloc(sizeof(int32_t));
     UChar              *patBuf = (UChar *)uprv_malloc(sizeof(UChar)*(actualPatLen+1));
     if (re == NULL || refC == NULL || patBuf == NULL) {
         *status = U_MEMORY_ALLOCATION_ERROR;
@@ -207,7 +207,7 @@ uregex_openUText(UText          *pattern,
     UErrorCode lengthStatus = U_ZERO_ERROR;
     int32_t pattern16Length = utext_extract(pattern, 0, patternNativeLength, NULL, 0, &lengthStatus);
     
-    atomic_int32_t     *refC   = (atomic_int32_t *)uprv_malloc(sizeof(int32_t));
+    u_atomic_int32_t   *refC   = (u_atomic_int32_t *)uprv_malloc(sizeof(int32_t));
     UChar              *patBuf = (UChar *)uprv_malloc(sizeof(UChar)*(pattern16Length+1));
     if (re == NULL || refC == NULL || patBuf == NULL) {
         *status = U_MEMORY_ALLOCATION_ERROR;
index 0621bd007914173cff8771b63cd3c33d1c59977b..2f6d7ecb42fe81e4907cbd3214b67e484eb689b8 100644 (file)
@@ -242,7 +242,7 @@ class SpoofData: public UMemory {
                                                     //   we are done.
 
     uint32_t                    fMemLimit;          // Limit of available raw data space
-    atomic_int32_t              fRefCount;
+    u_atomic_int32_t            fRefCount;
 
     // Confusable data
     int32_t                     *fCFUKeys;