]> granicus.if.org Git - icu/commitdiff
ICU-9461 Mutex Implementation Rework, merge from devel branch.
authorAndy Heninger <andy.heninger@gmail.com>
Fri, 5 Oct 2012 21:22:02 +0000 (21:22 +0000)
committerAndy Heninger <andy.heninger@gmail.com>
Fri, 5 Oct 2012 21:22:02 +0000 (21:22 +0000)
X-SVN-Rev: 32530

44 files changed:
icu4c/source/common/common.vcxproj
icu4c/source/common/common.vcxproj.filters
icu4c/source/common/listformatter.cpp
icu4c/source/common/mutex.h
icu4c/source/common/putil.cpp
icu4c/source/common/serv.cpp
icu4c/source/common/servls.cpp
icu4c/source/common/servnotf.cpp
icu4c/source/common/ubidi_props.c
icu4c/source/common/uchar.c
icu4c/source/common/ucln.h
icu4c/source/common/ucln_cmn.c
icu4c/source/common/ucnv_bld.cpp
icu4c/source/common/ucnvmbcs.c
icu4c/source/common/udata.cpp
icu4c/source/common/uinit.c
icu4c/source/common/umutex.c [deleted file]
icu4c/source/common/umutex.cpp [new file with mode: 0644]
icu4c/source/common/umutex.h
icu4c/source/common/uresbund.cpp
icu4c/source/common/usprep.cpp
icu4c/source/i18n/alphaindex.cpp
icu4c/source/i18n/astro.cpp
icu4c/source/i18n/chnsecal.cpp
icu4c/source/i18n/colldata.cpp
icu4c/source/i18n/dtfmtsym.cpp
icu4c/source/i18n/gender.cpp
icu4c/source/i18n/islamcal.cpp
icu4c/source/i18n/numfmt.cpp
icu4c/source/i18n/plurrule.cpp
icu4c/source/i18n/rbt.cpp
icu4c/source/i18n/smpdtfmt.cpp
icu4c/source/i18n/timezone.cpp
icu4c/source/i18n/translit.cpp
icu4c/source/i18n/tridpars.cpp
icu4c/source/i18n/tzfmt.cpp
icu4c/source/i18n/tzgnames.cpp
icu4c/source/i18n/tznames.cpp
icu4c/source/i18n/tznames_impl.cpp
icu4c/source/i18n/tznames_impl.h
icu4c/source/i18n/ucurr.cpp
icu4c/source/i18n/unicode/tzfmt.h
icu4c/source/i18n/zonemeta.cpp
icu4c/source/test/intltest/tsmthred.cpp

index c62a1a8e957e7601c9aae212d96d45b16adc74f8..9d708136d7d5fd246e6431bad62d782fe024e08c 100644 (file)
       <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</DisableLanguageExtensions>\r
     </ClCompile>\r
     <ClCompile Include="umath.c" />\r
-    <ClCompile Include="umutex.c">\r
+    <ClCompile Include="umutex.cpp">\r
       <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DisableLanguageExtensions>\r
       <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DisableLanguageExtensions>\r
       <DisableLanguageExtensions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</DisableLanguageExtensions>\r
index b87cefcf978e8ae6200cda14778c7b3ee68408e8..01b23c4e3b5d7fefb88f6ce047531444c7767939 100644 (file)
     <ClCompile Include="umath.c">\r
       <Filter>configuration</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="umutex.c">\r
+    <ClCompile Include="umutex.cpp">\r
       <Filter>configuration</Filter>\r
     </ClCompile>\r
     <ClCompile Include="utrace.c">\r
index 31c46484a2a0ca02b3c7ed6ea24630db4626e4c1..6a6e986377d8531d5cc8cb14e8c74a085d17b730 100644 (file)
@@ -25,7 +25,7 @@
 U_NAMESPACE_BEGIN
 
 static Hashtable* listPatternHash = NULL;
-static UMTX listFormatterMutex = NULL;
+static UMutex listFormatterMutex = U_MUTEX_INITIALIZER;
 static UChar FIRST_PARAMETER[] = { 0x7b, 0x30, 0x7d };  // "{0}"
 static UChar SECOND_PARAMETER[] = { 0x7b, 0x31, 0x7d };  // "{0}"
 
index 7f7ef897afaf7cf42019539222f26b73af7566c6..af8cd8cb9c24e0a72d149a409f0b72679e456d2a 100644 (file)
@@ -1,7 +1,7 @@
 /*
 ******************************************************************************
 *
-*   Copyright (C) 1997-2011, International Business Machines
+*   Copyright (C) 1997-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 ******************************************************************************
@@ -33,7 +33,7 @@ U_NAMESPACE_BEGIN
 
 // For example:
 // 
-// UMTX myMutex;
+// UMutex myMutex;
 // 
 // void Function(int arg1, int arg2)
 // {
@@ -50,17 +50,17 @@ U_NAMESPACE_BEGIN
 
 class U_COMMON_API Mutex : public UMemory {
 public:
-  inline Mutex(UMTX *mutex = NULL);
+  inline Mutex(UMutex *mutex = NULL);
   inline ~Mutex();
 
 private:
-  UMTX   *fMutex;
+  UMutex   *fMutex;
 
   Mutex(const Mutex &other); // forbid copying of this class
   Mutex &operator=(const Mutex &other); // forbid copying of this class
 };
 
-inline Mutex::Mutex(UMTX *mutex)
+inline Mutex::Mutex(UMutex *mutex)
   : fMutex(mutex)
 {
   umtx_lock(fMutex);
index 9946d8e1b655aeb0a0bf0f4e942cb6b58c0d44c6..4694aa9a8061bc503e0349d5fa635d0af41fdce7 100644 (file)
@@ -240,7 +240,7 @@ u_signBit(double d) {
 UDate fakeClock_t0 = 0; /** Time to start the clock from **/
 UDate fakeClock_dt = 0; /** Offset (fake time - real time) **/
 UBool fakeClock_set = FALSE; /** True if fake clock has spun up **/
-static UMTX fakeClockMutex = NULL;
+static UMutex fakeClockMutex = U_MUTEX_INTIALIZER;
 
 static UDate getUTCtime_real() {
     struct timeval posixTime;
index 2cddcfe65dcdcf3d4b266d273c111b26fb6e4df8..1a8c9166e043b124b2d753d79f393701fee61533 100644 (file)
@@ -1,6 +1,6 @@
 /**
 *******************************************************************************
-* Copyright (C) 2001-2011, International Business Machines Corporation.
+* Copyright (C) 2001-2012, International Business Machines Corporation.
 * All Rights Reserved.
 *******************************************************************************
 */
@@ -331,7 +331,7 @@ U_CDECL_END
 ******************************************************************
 */
 
-static UMTX lock;
+static UMutex lock = U_MUTEX_INITIALIZER;
 
 ICUService::ICUService()
 : name()
@@ -401,7 +401,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, UErrorCode&
 // reentrantly even without knowing the thread.
 class XMutex : public UMemory {
 public:
-    inline XMutex(UMTX *mutex, UBool reentering) 
+    inline XMutex(UMutex *mutex, UBool reentering) 
         : fMutex(mutex)
         , fActive(!reentering) 
     {
@@ -412,7 +412,7 @@ public:
     }
 
 private:
-    UMTX  *fMutex;
+    UMutex  *fMutex;
     UBool fActive;
 };
 
index 0e29bfcee6f34c87200e3bdddaf81e352518591b..418be4a5d9487554ad4dd0dca36568baeaed0054 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2001-2011, International Business Machines Corporation and    *
+ * Copyright (C) 2001-2012, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  *
@@ -25,7 +25,7 @@
 
 U_NAMESPACE_BEGIN
 
-static UMTX llock;
+static UMutex llock = U_MUTEX_INITIALIZER;
 ICULocaleService::ICULocaleService()
   : fallbackLocale(Locale::getDefault())
 {
index feecbc31dd214e4c2b6f8c899042bba1f97b9da9..dbcbe92df802df645adbe8fc9f01af9c6ffc0047 100644 (file)
@@ -1,6 +1,6 @@
 /**
  *******************************************************************************
- * Copyright (C) 2001-2011, International Business Machines Corporation and    *
+ * Copyright (C) 2001-2012, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -19,7 +19,7 @@ U_NAMESPACE_BEGIN
 EventListener::~EventListener() {}
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener)
 
-static UMTX notifyLock;
+static UMutex notifyLock = U_MUTEX_INITIALIZER;
 
 ICUNotifier::ICUNotifier(void) 
 : listeners(NULL) 
index 6fca5a3407427978472e2f3c9cc4a9b10144bd8c..e6f197431d2b752d31b80f7f0b1731dc7956ec8c 100644 (file)
@@ -1,7 +1,7 @@
 /*
 *******************************************************************************
 *
-*   Copyright (C) 2004-2011, International Business Machines
+*   Copyright (C) 2004-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 *
 *******************************************************************************
@@ -21,7 +21,6 @@
 #include "unicode/udata.h" /* UDataInfo */
 #include "ucmndata.h" /* DataHeader */
 #include "udatamem.h"
-#include "umutex.h"
 #include "uassert.h"
 #include "cmemory.h"
 #include "utrie2.h"
index d8520e216298e69b3b0802875ed9f9d886384d9e..53f92ffd6bec3846c45b4d68ac643def79c23391 100644 (file)
@@ -24,7 +24,6 @@
 #include "unicode/uscript.h"
 #include "unicode/udata.h"
 #include "uassert.h"
-#include "umutex.h"
 #include "cmemory.h"
 #include "ucln_cmn.h"
 #include "utrie2.h"
index 47f082a154ec900182a38bb634d9c63db4c204b8..2a83d9467ec9faa28a80826046083ad6348ecdf0 100644 (file)
@@ -18,7 +18,6 @@
 #define __UCLN_H__
 
 #include "unicode/utypes.h"
-#include "umutex.h"
 
 /** These are the functions used to register a library's memory cleanup
  * functions.  Each library should define a single library register function
index a7776ba4a6f9656049accd03377f4f9cdcc46dfe..513d796e58150f6dfd75e3b9c8018fb8a8fa3aaa 100644 (file)
@@ -26,7 +26,7 @@
 #include "ucln_imp.h"
 
 static UBool gICUInitialized = FALSE;
-static UMTX  gICUInitMutex   = NULL;
+static UMutex  gICUInitMutex = U_MUTEX_INITIALIZER;
 
 static cleanupFunc *gCommonCleanupFunctions[UCLN_COMMON_COUNT];
 static cleanupFunc *gLibCleanupFunctions[UCLN_COMMON];
@@ -58,7 +58,6 @@ u_cleanup(void)
 
     ucln_lib_cleanup();
 
-    umtx_destroy(&gICUInitMutex);
     umtx_cleanup();
     cmemory_cleanup();       /* undo any heap functions set by u_setMemoryFunctions(). */
     gICUInitialized = FALSE;
index 02159f97d0e625afa7758a050cbbdce10f4f8a75..9532620c57dae90fb88a32d92af9b4d606688517 100644 (file)
@@ -159,9 +159,9 @@ static struct {
 
 /*initializes some global variables */
 static UHashtable *SHARED_DATA_HASHTABLE = NULL;
-static UMTX        cnvCacheMutex = NULL;  /* Mutex for synchronizing cnv cache access. */
-                                          /*  Note:  the global mutex is used for      */
-                                          /*         reference count updates.          */
+static UMutex cnvCacheMutex = U_MUTEX_INITIALIZER;  /* Mutex for synchronizing cnv cache access. */
+                                                    /*  Note:  the global mutex is used for      */
+                                                    /*         reference count updates.          */
 
 static const char **gAvailableConverters = NULL;
 static uint16_t gAvailableConverterCount = 0;
@@ -219,9 +219,6 @@ static UBool U_CALLCONV ucnv_cleanup(void) {
     gDefaultAlgorithmicSharedData = NULL;
 #endif
 
-    umtx_destroy(&cnvCacheMutex);    /* Don't worry about destroying the mutex even  */
-                                     /*  if the hash table still exists.  The mutex  */
-                                     /*  will lazily re-init  itself if needed.      */
     return (SHARED_DATA_HASHTABLE == NULL);
 }
 
index f3d83a3625e138e59a471c7454bff5e9ccd84943..f88adf1d8d58e97da6b643b6a0b9a72483348580 100644 (file)
@@ -54,9 +54,9 @@
 #include "ucnvmbcs.h"
 #include "ucnv_ext.h"
 #include "ucnv_cnv.h"
-#include "umutex.h"
 #include "cmemory.h"
 #include "cstring.h"
+#include "umutex.h"
 
 /* control optimizations according to the platform */
 #define MBCS_UNROLL_SINGLE_TO_BMP 1
index c4f8752a4ebb010ec4bf200884ea5c37a393c9fc..0837893eeb0fa8f71b1df87c33c77b3f3bb8e936 100644 (file)
@@ -806,7 +806,7 @@ static UBool extendICUData(UErrorCode *pErr)
      * Use a specific mutex to avoid nested locks of the global mutex.
      */
 #if MAP_IMPLEMENTATION==MAP_STDIO
-    static UMTX extendICUDataMutex = NULL;
+    static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER;
     umtx_lock(&extendICUDataMutex);
 #endif
     if(!gHaveTriedToLoadCommonData) {
index 44d496acbd474e5d779e43a8a3d22ddbd5435644..db3f252c5fbfe4724a83254ca14a4f050d14ac4d 100644 (file)
@@ -21,7 +21,6 @@
 #include "icuplugimp.h"
 #include "ucln.h"
 #include "ucnv_io.h"
-#include "umutex.h"
 #include "utracimp.h"
 
 static void U_CALLCONV
diff --git a/icu4c/source/common/umutex.c b/icu4c/source/common/umutex.c
deleted file mode 100644 (file)
index e36c241..0000000
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
-******************************************************************************
-*
-*   Copyright (C) 1997-2012, International Business Machines
-*   Corporation and others.  All Rights Reserved.
-*
-******************************************************************************
-*
-* File umutex.c
-*
-* Modification History:
-*
-*   Date        Name        Description
-*   04/02/97    aliu        Creation.
-*   04/07/99    srl         updated
-*   05/13/99    stephen     Changed to umutex (from cmutex).
-*   11/22/99    aliu        Make non-global mutex autoinitialize [j151]
-******************************************************************************
-*/
-
-#include "unicode/utypes.h"
-#include "uassert.h"
-#include "ucln_cmn.h"
-
-/*
- * ICU Mutex wrappers.  Wrap operating system mutexes, giving the rest of ICU a
- * platform independent set of mutex operations.  For internal ICU use only.
- */
-
-#if U_PLATFORM_HAS_WIN32_API
-    /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
-#   undef POSIX
-#elif U_PLATFORM_IMPLEMENTS_POSIX
-#   define POSIX
-#else
-#   undef POSIX
-#endif
-
-#if defined(POSIX)
-# include <pthread.h> /* must be first, so that we get the multithread versions of things. */
-
-#endif /* POSIX */
-
-#if U_PLATFORM_HAS_WIN32_API
-# define WIN32_LEAN_AND_MEAN
-# define VC_EXTRALEAN
-# define NOUSER
-# define NOSERVICE
-# define NOIME
-# define NOMCX
-# include <windows.h>
-#endif
-
-#include "umutex.h"
-#include "cmemory.h"
-
-/*
- * A note on ICU Mutex Initialization and ICU startup:
- *
- *   ICU mutexes, as used through the rest of the ICU code, are self-initializing.
- *   To make this work, ICU uses the _ICU GLobal Mutex_ to synchronize the lazy init
- *   of other ICU mutexes.  For the global mutex itself, we need some other mechanism
- *   to safely initialize it on first use.  This becomes important when two or more
- *   threads are more or less simultaenously the first to use ICU in a process, and
- *   are racing into the mutex initialization code.
- *
- *
- *   The solution for the global mutex init is platform dependent.
- *   On POSIX systems, plain C-style initialization can be used on a mutex, with the 
- *   macro PTHREAD_MUTEX_INITIALIZER.  The mutex is then ready for use, without
- *   first calling pthread_mutex_init().
- *
- *   Windows has no equivalent statically initialized mutex or CRITICAL SECION.
- *   InitializeCriticalSection() must be called.  If the global mutex does not
- *   appear to be initialized, a thread will create and initialize a new
- *   CRITICAL_SECTION, then use a Windows InterlockedCompareAndExchange to
- *   swap it in as the global mutex while avoid problems with race conditions.
- */ 
-
-/* On WIN32 mutexes are reentrant.  On POSIX platforms they are not, and a deadlock
- *  will occur if a thread attempts to acquire a mutex it already has locked.
- *  ICU mutexes (in debug builds) include checking code that will cause an assertion
- *  failure if a mutex is reentered.  If you are having deadlock problems
- *  on a POSIX machine, debugging may be easier on Windows.
- */
-
-
-#if U_PLATFORM_HAS_WIN32_API
-#define MUTEX_TYPE CRITICAL_SECTION
-#define PLATFORM_MUTEX_INIT(m) InitializeCriticalSection(m)
-#define PLATFORM_MUTEX_LOCK(m) EnterCriticalSection(m)
-#define PLATFORM_MUTEX_UNLOCK(m) LeaveCriticalSection(m)
-#define PLATFORM_MUTEX_DESTROY(m) DeleteCriticalSection(m)
-#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
-            InterlockedCompareExchangePointer(dest, newval, oldval)
-
-
-#elif defined(POSIX)
-#define MUTEX_TYPE pthread_mutex_t   
-#define PLATFORM_MUTEX_INIT(m) pthread_mutex_init(m, NULL)
-#define PLATFORM_MUTEX_LOCK(m) pthread_mutex_lock(m)
-#define PLATFORM_MUTEX_UNLOCK(m) pthread_mutex_unlock(m)
-#define PLATFORM_MUTEX_DESTROY(m) pthread_mutex_destroy(m)
-#define PLATFORM_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
-#if (U_HAVE_GCC_ATOMICS == 1)
-#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
-            __sync_val_compare_and_swap(dest, oldval, newval)
-#else
-#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
-            mutexed_compare_and_swap(dest, newval, oldval)
-#endif
-
-
-#else   
-/* Unknown platform.  Note that user can still set mutex functions at run time. */
-#define MUTEX_TYPE void *
-#define PLATFORM_MUTEX_INIT(m) 
-#define PLATFORM_MUTEX_LOCK(m)
-#define PLATFORM_MUTEX_UNLOCK(m) 
-#define PLATFORM_MUTEX_DESTROY(m) 
-#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
-            mutexed_compare_and_swap(dest, newval, oldval)
-
-#endif
-
-/*  Forward declarations */
-static void *mutexed_compare_and_swap(void **dest, void *newval, void *oldval);
-typedef struct ICUMutex ICUMutex;
-
-/*
- * ICUMutex   One of these is set up for each UMTX that is used by other ICU code.
- *            The opaque UMTX points to the corresponding ICUMutex struct.
- *            
- *            Because the total number of ICU mutexes is quite small, no effort has
- *            been made to squeeze every byte out of this struct.
- */
-struct ICUMutex {
-    UMTX        *owner;             /* Points back to the UMTX corrsponding to this   */
-                                    /*    ICUMutex object.                            */
-    
-    UBool        heapAllocated;     /* Set if this ICUMutex is heap allocated, and    */
-                                    /*   will need to be deleted.  The global mutex   */
-                                    /*   is static on POSIX platforms; all others     */
-                                    /*   will be heap allocated.                      */
-
-    ICUMutex    *next;              /* All ICUMutexes are chained into a list so that  */
-                                    /*   they can be found and deleted by u_cleanup(). */
-
-    int32_t      recursionCount;    /* For debugging, detect recursive mutex locks.    */
-
-    MUTEX_TYPE   platformMutex;     /* The underlying OS mutex being wrapped.          */
-
-    UMTX         userMutex;         /* For use with u_setMutexFunctions operations,    */
-                                    /*    corresponds to platformMutex.                */
-};
-
-
-/*   The global ICU mutex.
- *   For POSIX platforms, it gets a C style initialization, and is ready to use
- *        at program startup.
- *   For Windows, it will be lazily instantiated on first use.
- */
-
-#if defined(POSIX)
-static UMTX  globalUMTX;
-static ICUMutex globalMutex = {&globalUMTX, FALSE, NULL, 0, PLATFORM_MUTEX_INITIALIZER, NULL};
-static UMTX  globalUMTX = &globalMutex;
-#else
-static UMTX  globalUMTX = NULL;
-#endif
-
-/* Head of the list of all ICU mutexes.
- * Linked list is through ICUMutex::next
- * Modifications to the list are synchronized with the global mutex.
- * The list is used by u_cleanup(), which needs to dispose of all of the ICU mutexes.
- *
- * The statically initialized global mutex on POSIX platforms does not get added to this
- * mutex list, but that's not a problem - the global mutex gets special handling
- * during u_cleanup().
- */
-static ICUMutex *mutexListHead;
-
-
-/*
- *  User mutex implementation functions.  If non-null, call back to these rather than
- *  directly using the system (Posix or Windows) APIs.  See u_setMutexFunctions().
- *    (declarations are in uclean.h)
- */
-static UMtxInitFn    *pMutexInitFn    = NULL;
-static UMtxFn        *pMutexDestroyFn = NULL;
-static UMtxFn        *pMutexLockFn    = NULL;
-static UMtxFn        *pMutexUnlockFn  = NULL;
-static const void    *gMutexContext   = NULL;
-
-
-/*
- *   umtx_lock
- */
-U_CAPI void  U_EXPORT2
-umtx_lock(UMTX *mutex)
-{
-    ICUMutex *m;
-
-    if (mutex == NULL) {
-        mutex = &globalUMTX;
-    }
-    m = (ICUMutex *)*mutex;
-    if (m == NULL) {
-        /* See note on lazy initialization, above.  We can get away with it here, with mutexes,
-         * where we couldn't with normal user level data.
-         */
-        umtx_init(mutex);    
-        m = (ICUMutex *)*mutex;
-    }
-    U_ASSERT(m->owner == mutex);
-
-    if (pMutexLockFn != NULL) {
-        (*pMutexLockFn)(gMutexContext, &m->userMutex);
-    } else {
-        PLATFORM_MUTEX_LOCK(&m->platformMutex);
-    }
-
-#if defined(U_DEBUG)
-    m->recursionCount++;              /* Recursion causes deadlock on Unixes.               */
-    U_ASSERT(m->recursionCount == 1); /* Recursion detection works on Windows.              */
-                                      /* Assertion failure on non-Windows indicates a       */
-                                      /*   problem with the mutex implementation itself.    */
-#endif
-}
-
-
-
-/*
- * umtx_unlock
- */
-U_CAPI void  U_EXPORT2
-umtx_unlock(UMTX* mutex)
-{
-    ICUMutex *m;
-    if(mutex == NULL) {
-        mutex = &globalUMTX;
-    }
-    m = (ICUMutex *)*mutex;
-    if (m == NULL) {
-        U_ASSERT(FALSE);  /* This mutex is not initialized.     */
-        return; 
-    }
-    U_ASSERT(m->owner == mutex);
-
-#if defined (U_DEBUG)
-    m->recursionCount--;
-    U_ASSERT(m->recursionCount == 0);  /* Detect unlock of an already unlocked mutex */
-#endif
-
-    if (pMutexUnlockFn) {
-        (*pMutexUnlockFn)(gMutexContext, &m->userMutex);
-    } else {
-        PLATFORM_MUTEX_UNLOCK(&m->platformMutex);
-    }
-}
-
-
-/* umtx_ct   Allocate and initialize a new ICUMutex.
- *           If a non-null pointer is supplied, initialize an existing ICU Mutex.
- */
-static ICUMutex *umtx_ct(ICUMutex *m) {
-    if (m == NULL) {
-        m = (ICUMutex *)uprv_malloc(sizeof(ICUMutex));
-        m->heapAllocated = TRUE;
-    }
-    m->next = NULL;    /* List of mutexes is maintained at a higher level.  */
-    m->recursionCount = 0;
-    m->userMutex = NULL;
-    if (pMutexInitFn != NULL) {
-        UErrorCode status = U_ZERO_ERROR;
-        (*pMutexInitFn)(gMutexContext, &m->userMutex, &status);
-        U_ASSERT(U_SUCCESS(status));
-    } else {
-        PLATFORM_MUTEX_INIT(&m->platformMutex);
-    }
-    return m;
-}
-
-
-/* umtx_dt   Delete a ICUMutex.  Destroy the underlying OS Platform mutex.
- *           Does not touch the linked list of ICU Mutexes.
- */
-static void umtx_dt(ICUMutex *m) {
-    if (pMutexDestroyFn != NULL) {
-        (*pMutexDestroyFn)(gMutexContext, &m->userMutex);
-        m->userMutex = NULL;
-    } else {
-        PLATFORM_MUTEX_DESTROY(&m->platformMutex);
-    }
-
-    if (m->heapAllocated) {
-        uprv_free(m);
-    }
-}
-    
-
-U_CAPI void  U_EXPORT2
-umtx_init(UMTX *mutex) {
-    ICUMutex *m = NULL;
-    void *originalValue;
-
-    if (*mutex != NULL) {
-        /* Mutex is already initialized.  
-         * Multiple umtx_init()s of a UMTX by other ICU code are explicitly permitted.
-         */
-        return;
-    }
-#if defined(POSIX)
-    if (mutex == &globalUMTX) {
-        m = &globalMutex;
-    }
-#endif
-
-    m = umtx_ct(m);
-    originalValue = SYNC_COMPARE_AND_SWAP(mutex, NULL, m);
-    if (originalValue != NULL) {
-        umtx_dt(m);
-        return;
-    }
-
-    m->owner = mutex;
-
-    /* Hook the new mutex into the list of all ICU mutexes, so that we can find and
-     * delete it for u_cleanup().
-     */
-
-    umtx_lock(NULL);
-    m->next = mutexListHead;
-    mutexListHead = m;
-    umtx_unlock(NULL);
-    return;
-}
-
-
-/*
- *  umtx_destroy.    Un-initialize a mutex, releasing any underlying resources
- *                   that it may be holding.  Destroying an already destroyed
- *                   mutex has no effect.  Unlike umtx_init(), this function
- *                   is not thread safe;  two threads must not concurrently try to
- *                   destroy the same mutex.
- */                  
-U_CAPI void  U_EXPORT2
-umtx_destroy(UMTX *mutex) {
-    ICUMutex *m;
-    
-    /* No one should be deleting the global ICU mutex. 
-     *   (u_cleanup() does delete it, but does so explicitly, not by passing NULL)
-     */
-    U_ASSERT(mutex != NULL);
-    if (mutex == NULL) { 
-        return;
-    }
-    
-    m = (ICUMutex *)*mutex;
-    if (m == NULL) {  /* Mutex not initialized, or already destroyed.  */
-        return;
-    }
-
-    U_ASSERT(m->owner == mutex);
-    if (m->owner != mutex) {
-        return;
-    }
-
-    /* Remove this mutex from the linked list of mutexes.  */
-    umtx_lock(NULL);
-    if (mutexListHead == m) {
-        mutexListHead = m->next;
-    } else {
-        ICUMutex *prev;
-        for (prev = mutexListHead; prev!=NULL && prev->next!=m; prev = prev->next);
-            /*  Empty for loop body */
-        if (prev != NULL) {
-            prev->next = m->next;
-        }
-    }
-    umtx_unlock(NULL);
-
-    umtx_dt(m);        /* Delete the internal ICUMutex   */
-    *mutex = NULL;     /* Clear the caller's UMTX        */
-}
-
-
-
-U_CAPI void U_EXPORT2 
-u_setMutexFunctions(const void *context, UMtxInitFn *i, UMtxFn *d, UMtxFn *l, UMtxFn *u,
-                    UErrorCode *status) {
-    if (U_FAILURE(*status)) {
-        return;
-    }
-
-    /* Can not set a mutex function to a NULL value  */
-    if (i==NULL || d==NULL || l==NULL || u==NULL) {
-        *status = U_ILLEGAL_ARGUMENT_ERROR;
-        return;
-    }
-
-    /* If ICU is not in an initial state, disallow this operation. */
-    if (cmemory_inUse()) {
-        *status = U_INVALID_STATE_ERROR;
-        return;
-    }
-    
-    /* Kill any existing global mutex.  POSIX platforms have a global mutex
-     * even before any other part of ICU is initialized.
-     */
-    umtx_destroy(&globalUMTX);
-
-    /* Swap in the mutex function pointers.  */
-    pMutexInitFn    = i;
-    pMutexDestroyFn = d;
-    pMutexLockFn    = l;
-    pMutexUnlockFn  = u;
-    gMutexContext   = context;
-
-#if defined (POSIX) 
-    /* POSIX platforms must have a pre-initialized global mutex 
-     * to allow other mutexes to initialize safely. */
-    umtx_init(&globalUMTX);
-#endif
-}
-
-
-/*   synchronized compare and swap function, for use when OS or compiler built-in
- *   equivalents aren't available.
- *
- *   This operation relies on the ICU global mutex for synchronization.
- *
- *   There are two cases where this function can be entered when the global mutex is not
- *   yet initialized - at the end  u_cleanup(), and at the end of u_setMutexFunctions, both
- *   of which re-init the global mutex.  But neither function is thread-safe, so the lack of
- *   synchronization at these points doesn't matter.
- */
-static void *mutexed_compare_and_swap(void **dest, void *newval, void *oldval) {
-    void *temp;
-    UBool needUnlock = FALSE;
-
-    if (globalUMTX != NULL) {
-        umtx_lock(&globalUMTX);
-        needUnlock = TRUE;
-    }
-
-    temp = *dest;
-    if (temp == oldval) {
-        *dest = newval;
-    }
-    
-    if (needUnlock) {
-        umtx_unlock(&globalUMTX);
-    }
-    return temp;
-}
-
-
-
-/*-----------------------------------------------------------------
- *
- *  Atomic Increment and Decrement
- *     umtx_atomic_inc
- *     umtx_atomic_dec
- *
- *----------------------------------------------------------------*/
-
-/* Pointers to user-supplied inc/dec functions.  Null if no funcs have been set.  */
-static UMtxAtomicFn  *pIncFn = NULL;
-static UMtxAtomicFn  *pDecFn = NULL;
-static const void *gIncDecContext  = NULL;
-
-static UMTX    gIncDecMutex = NULL;
-
-U_CAPI int32_t U_EXPORT2
-umtx_atomic_inc(int32_t *p)  {
-    int32_t retVal;
-    if (pIncFn) {
-        retVal = (*pIncFn)(gIncDecContext, p);
-    } else {
-        #if U_PLATFORM_HAS_WIN32_API
-            retVal = InterlockedIncrement((LONG*)p);
-        #elif defined(USE_MAC_OS_ATOMIC_INCREMENT)
-            retVal = OSAtomicIncrement32Barrier(p);
-        #elif (U_HAVE_GCC_ATOMICS == 1)
-            retVal = __sync_add_and_fetch(p, 1);
-        #elif defined (POSIX)
-            umtx_lock(&gIncDecMutex);
-            retVal = ++(*p);
-            umtx_unlock(&gIncDecMutex);
-        #else
-            /* Unknown Platform. */
-            retVal = ++(*p);
-        #endif
-    }
-    return retVal;
-}
-
-U_CAPI int32_t U_EXPORT2
-umtx_atomic_dec(int32_t *p) {
-    int32_t retVal;
-    if (pDecFn) {
-        retVal = (*pDecFn)(gIncDecContext, p);
-    } else {
-        #if U_PLATFORM_HAS_WIN32_API
-            retVal = InterlockedDecrement((LONG*)p);
-        #elif defined(USE_MAC_OS_ATOMIC_INCREMENT)
-            retVal = OSAtomicDecrement32Barrier(p);
-        #elif (U_HAVE_GCC_ATOMICS == 1)
-            retVal = __sync_sub_and_fetch(p, 1);
-        #elif defined (POSIX)
-            umtx_lock(&gIncDecMutex);
-            retVal = --(*p);
-            umtx_unlock(&gIncDecMutex);
-        #else
-            /* Unknown Platform. */
-            retVal = --(*p);
-        #endif
-    }
-    return retVal;
-}
-
-
-
-U_CAPI void U_EXPORT2
-u_setAtomicIncDecFunctions(const void *context, UMtxAtomicFn *ip, UMtxAtomicFn *dp,
-                                UErrorCode *status) {
-    if (U_FAILURE(*status)) {
-        return;
-    }
-    /* Can not set a mutex function to a NULL value  */
-    if (ip==NULL || dp==NULL) {
-        *status = U_ILLEGAL_ARGUMENT_ERROR;
-        return;
-    }
-    /* If ICU is not in an initial state, disallow this operation. */
-    if (cmemory_inUse()) {
-        *status = U_INVALID_STATE_ERROR;
-        return;
-    }
-
-    pIncFn = ip;
-    pDecFn = dp;
-    gIncDecContext = context;
-
-#if U_DEBUG
-    {
-        int32_t   testInt = 0;
-        U_ASSERT(umtx_atomic_inc(&testInt) == 1);     /* Sanity Check.    Do the functions work at all? */
-        U_ASSERT(testInt == 1);
-        U_ASSERT(umtx_atomic_dec(&testInt) == 0);
-        U_ASSERT(testInt == 0);
-    }
-#endif
-}
-
-
-
-/*
- *  Mutex Cleanup Function
- *
- *      Destroy the global mutex(es), and reset the mutex function callback pointers.
- */
-U_CFUNC UBool umtx_cleanup(void) {
-    ICUMutex *thisMutex = NULL;
-    ICUMutex *nextMutex = NULL;
-
-    /* Extra, do-nothing function call to suppress compiler warnings on platforms where
-     *   mutexed_compare_and_swap is not otherwise used.  */
-    mutexed_compare_and_swap(&globalUMTX, NULL, NULL);
-
-    /* Delete all of the ICU mutexes.  Do the global mutex last because it is used during
-     * the umtx_destroy operation of other mutexes.
-     */
-    for (thisMutex=mutexListHead; thisMutex!=NULL; thisMutex=nextMutex) {
-        UMTX *umtx = thisMutex->owner;
-        nextMutex = thisMutex->next;
-        U_ASSERT(*umtx = (void *)thisMutex);
-        if (umtx != &globalUMTX) {
-            umtx_destroy(umtx);
-        }
-    }
-    umtx_destroy(&globalUMTX);
-        
-    pMutexInitFn    = NULL;
-    pMutexDestroyFn = NULL;
-    pMutexLockFn    = NULL;
-    pMutexUnlockFn  = NULL;
-    gMutexContext   = NULL;
-    pIncFn          = NULL;
-    pDecFn          = NULL;
-    gIncDecContext  = NULL;
-    gIncDecMutex    = NULL;
-
-#if defined (POSIX) 
-    /* POSIX platforms must come out of u_cleanup() with a functioning global mutex 
-     * to permit the safe resumption of use of ICU in multi-threaded environments. 
-     */
-    umtx_init(&globalUMTX);
-#endif
-    return TRUE;
-}
-
-
diff --git a/icu4c/source/common/umutex.cpp b/icu4c/source/common/umutex.cpp
new file mode 100644 (file)
index 0000000..a7299a5
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+******************************************************************************
+*
+*   Copyright (C) 1997-2012, International Business Machines
+*   Corporation and others.  All Rights Reserved.
+*
+******************************************************************************
+*
+* File umutex.cpp
+*
+* Modification History:
+*
+*   Date        Name        Description
+*   04/02/97    aliu        Creation.
+*   04/07/99    srl         updated
+*   05/13/99    stephen     Changed to umutex (from cmutex).
+*   11/22/99    aliu        Make non-global mutex autoinitialize [j151]
+******************************************************************************
+*/
+
+#include "unicode/utypes.h"
+#include "uassert.h"
+#include "ucln_cmn.h"
+
+/*
+ * ICU Mutex wrappers.  Wrap operating system mutexes, giving the rest of ICU a
+ * platform independent set of mutex operations.  For internal ICU use only.
+ */
+
+#if U_PLATFORM_HAS_WIN32_API
+    /* Prefer native Windows APIs even if POSIX is implemented (i.e., on Cygwin). */
+#   undef POSIX
+#elif U_PLATFORM_IMPLEMENTS_POSIX
+#   define POSIX
+#else
+#   undef POSIX
+#endif
+
+#if defined(POSIX)
+# include <pthread.h> /* must be first, so that we get the multithread versions of things. */
+#endif /* POSIX */
+
+#if U_PLATFORM_HAS_WIN32_API
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# define NOUSER
+# define NOSERVICE
+# define NOIME
+# define NOMCX
+# include <windows.h>
+#endif
+
+#include "umutex.h"
+#include "cmemory.h"
+
+#if U_PLATFORM_HAS_WIN32_API
+#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
+            InterlockedCompareExchangePointer(dest, newval, oldval)
+
+#elif defined(POSIX)
+#if (U_HAVE_GCC_ATOMICS == 1)
+#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
+            __sync_val_compare_and_swap(dest, oldval, newval)
+#else
+#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
+            mutexed_compare_and_swap(dest, newval, oldval)
+#endif
+
+#else   
+// Unknown platform.  Note that user can still set mutex functions at run time.
+#define SYNC_COMPARE_AND_SWAP(dest, oldval, newval) \
+            mutexed_compare_and_swap(dest, newval, oldval)
+#endif
+
+static void *mutexed_compare_and_swap(void **dest, void *newval, void *oldval);
+
+// The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer.
+static UMutex   globalMutex = U_MUTEX_INITIALIZER;
+
+// Implementation mutex. Used for compare & swap when no intrinsic is available, and
+// for safe initialization of user defined mutexes.
+static UMutex   implMutex = U_MUTEX_INITIALIZER;      
+
+// List of all user mutexes that have been initialized.
+// Used to allow us to destroy them when cleaning up ICU.
+// Normal platform mutexes are not kept track of in this way - they survive until the process is shut down.
+// Normal platfrom mutexes don't allocate storage, so not cleaning them up won't trigger memory leak complaints.
+//
+// Note: putting this list in allocated memory would be awkward to arrange, because memory allocations
+//       are used as a flag to indicate that ICU has been initialized, and setting other ICU 
+//       override functions will no longer work.
+//
+static const int MUTEX_LIST_LIMIT = 100;
+static UMutex *gMutexList[MUTEX_LIST_LIMIT];
+static int gMutexListSize = 0;
+
+
+/*
+ *  User mutex implementation functions.  If non-null, call back to these rather than
+ *  directly using the system (Posix or Windows) APIs.  See u_setMutexFunctions().
+ *    (declarations are in uclean.h)
+ */
+static UMtxInitFn    *pMutexInitFn    = NULL;
+static UMtxFn        *pMutexDestroyFn = NULL;
+static UMtxFn        *pMutexLockFn    = NULL;
+static UMtxFn        *pMutexUnlockFn  = NULL;
+static const void    *gMutexContext   = NULL;
+
+
+// Clean up (undo) the effects of u_setMutexFunctions().
+//
+static void usrMutexCleanup() {
+    if (pMutexDestroyFn != NULL) {
+        for (int i = 0; i < gMutexListSize; i++) {
+            UMutex *m = gMutexList[i];
+            U_ASSERT(m->fInitialized);
+            (*pMutexDestroyFn)(gMutexContext, &m->fUserMutex);
+            m->fInitialized = FALSE;
+        }
+        (*pMutexDestroyFn)(gMutexContext, &globalMutex.fUserMutex);
+        (*pMutexDestroyFn)(gMutexContext, &implMutex.fUserMutex);
+    }
+    gMutexListSize  = 0;
+    pMutexInitFn    = NULL;
+    pMutexDestroyFn = NULL;
+    pMutexLockFn    = NULL;
+    pMutexUnlockFn  = NULL;
+    gMutexContext   = NULL;
+}
+
+
+/*
+ * User mutex lock.
+ *
+ * User mutexes need to be initialized before they can be used. We use the impl mutex
+ * to synchronize the initialization check. This could be sped up on platforms that
+ * support alternate ways to safely check the initialization flag.
+ *
+ */
+static void usrMutexLock(UMutex *mutex) {
+    UErrorCode status = U_ZERO_ERROR;
+    if (!(mutex == &implMutex || mutex == &globalMutex)) {
+        umtx_lock(&implMutex);
+        if (!mutex->fInitialized) {
+            (*pMutexInitFn)(gMutexContext, &mutex->fUserMutex, &status);
+            U_ASSERT(U_SUCCESS(status));
+            mutex->fInitialized = TRUE;
+            U_ASSERT(gMutexListSize < MUTEX_LIST_LIMIT);
+            if (gMutexListSize < MUTEX_LIST_LIMIT) {
+                gMutexList[gMutexListSize] = mutex;
+                ++gMutexListSize;
+            }
+        }
+        umtx_unlock(&implMutex);
+    }
+    (*pMutexLockFn)(gMutexContext, &mutex->fUserMutex);
+}
+        
+
+
+#if defined(POSIX)
+
+//
+// POSIX implementation of UMutex.
+//
+// Each UMutex has a corresponding pthread_mutex_t.
+// All are statically initialized and ready for use.
+// There is no runtime mutex initialization code needed.
+
+U_CAPI void  U_EXPORT2
+umtx_lock(UMutex *mutex) {
+    if (mutex == NULL) {
+        mutex = &globalMutex;
+    }
+    if (pMutexLockFn) {
+        usrMutexLock(mutex);
+    } else {
+        #if U_DEBUG
+            // #if to avoid unused variable warnings in non-debug builds.
+            int sysErr = pthread_mutex_lock(&mutex->fMutex);
+            U_ASSERT(sysErr == 0);
+        #else
+            pthread_mutex_lock(&mutex->fMutex);
+        #endif
+    }
+}
+
+
+U_CAPI void  U_EXPORT2
+umtx_unlock(UMutex* mutex)
+{
+    if (mutex == NULL) {
+        mutex = &globalMutex;
+    }
+    if (pMutexUnlockFn) {
+        (*pMutexUnlockFn)(gMutexContext, &mutex->fUserMutex);
+    } else {
+        #if U_DEBUG
+            // #if to avoid unused variable warnings in non-debug builds.
+            int sysErr = pthread_mutex_unlock(&mutex->fMutex);
+            U_ASSERT(sysErr == 0);
+        #else
+            pthread_mutex_unlock(&mutex->fMutex);
+        #endif
+    }
+}
+
+#elif U_PLATFORM_HAS_WIN32_API
+//
+// Windows implementation of UMutex.
+//
+// Each UMutex has a corresponding Windows CRITICAL_SECTION.
+// CRITICAL_SECTIONS must be initialized before use. This is done
+//   with a InitOnceExcuteOnce operation.
+//
+// InitOnceExecuteOnce was introduced with Windows Vista. For now ICU
+// must support Windows XP, so we roll our own. ICU will switch to the
+// native Windows InitOnceExecuteOnce when possible.
+
+typedef UBool (*U_PINIT_ONCE_FN) (
+  U_INIT_ONCE     *initOnce,
+  void            *parameter,
+  void            **context
+);
+
+UBool u_InitOnceExecuteOnce(
+  U_INIT_ONCE     *initOnce,
+  U_PINIT_ONCE_FN initFn,
+  void            *parameter,
+  void            **context) {
+      for (;;) {
+          long previousState = InterlockedCompareExchange( 
+              &initOnce->fState,  //  Destination,
+              1,                  //  Exchange Value
+              0);                 //  Compare value
+          if (previousState == 2) {
+              // Initialization was already completed.
+              if (context != NULL) {
+                  *context = initOnce->fContext;
+              }
+              return TRUE;
+          }
+          if (previousState == 1) {
+              // Initialization is in progress in some other thread.
+              // Loop until it completes.
+              Sleep(1);
+              continue;
+          }
+           
+          // Initialization needed. Execute the callback function to do it.
+          U_ASSERT(previousState == 0);
+          U_ASSERT(initOnce->fState == 1);
+          UBool success = (*initFn)(initOnce, parameter, &initOnce->fContext);
+          U_ASSERT(success); // ICU is not supporting the failure case.
+
+          // Assign the state indicating that initialization has completed.
+          // Using InterlockedCompareExchange to do it ensures that all
+          // threads will have a consistent view of memory.
+          previousState = InterlockedCompareExchange(&initOnce->fState, 2, 1);
+          U_ASSERT(previousState == 1);
+          // Next loop iteration will see the initialization and return.
+      }
+};
+
+static UBool winMutexInit(U_INIT_ONCE *initOnce, void *param, void **context) {
+    UMutex *mutex = static_cast<UMutex *>(param);
+    U_ASSERT(sizeof(CRITICAL_SECTION) <= sizeof(mutex->fCS));
+    InitializeCriticalSection((CRITICAL_SECTION *)mutex->fCS);
+    return TRUE;
+}
+
+/*
+ *   umtx_lock
+ */
+U_CAPI void  U_EXPORT2
+umtx_lock(UMutex *mutex) {
+    if (mutex == NULL) {
+        mutex = &globalMutex;
+    }
+    if (pMutexLockFn) {
+        usrMutexLock(mutex);
+    } else {
+        u_InitOnceExecuteOnce(&mutex->fInitOnce, winMutexInit, mutex, NULL);
+        EnterCriticalSection((CRITICAL_SECTION *)mutex->fCS);
+    }
+}
+
+U_CAPI void  U_EXPORT2
+umtx_unlock(UMutex* mutex)
+{
+    if (mutex == NULL) {
+        mutex = &globalMutex;
+    }
+    if (pMutexUnlockFn) {
+        (*pMutexUnlockFn)(gMutexContext, &mutex->fUserMutex);
+    } else {
+        LeaveCriticalSection((CRITICAL_SECTION *)mutex->fCS);
+    }
+}
+
+#endif  // Windows Implementation
+
+
+U_CAPI void U_EXPORT2 
+u_setMutexFunctions(const void *context, UMtxInitFn *i, UMtxFn *d, UMtxFn *l, UMtxFn *u,
+                    UErrorCode *status) {
+    if (U_FAILURE(*status)) {
+        return;
+    }
+
+    /* Can not set a mutex function to a NULL value  */
+    if (i==NULL || d==NULL || l==NULL || u==NULL) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+
+    /* If ICU is not in an initial state, disallow this operation. */
+    if (cmemory_inUse()) {
+        *status = U_INVALID_STATE_ERROR;
+        return;
+    }
+
+    // Clean up any previously set user mutex functions.
+    // It's possible to call u_setMutexFunctions() more than once without without explicitly cleaning up,
+    // and the last call should take. Kind of a corner case, but it worked once, there is a test for
+    // it, so we keep it working. The global and impl mutexes will have been created by the
+    // previous u_setMutexFunctions(), and now need to be destroyed.
+
+    usrMutexCleanup();
+    
+    /* Swap in the mutex function pointers.  */
+    pMutexInitFn    = i;
+    pMutexDestroyFn = d;
+    pMutexLockFn    = l;
+    pMutexUnlockFn  = u;
+    gMutexContext   = context;
+    gMutexListSize  = 0;
+
+    /* Initialize the global and impl mutexes. Safe to do at this point because
+     * u_setMutexFunctions must be done in a single-threaded envioronment. Not thread safe.
+     */
+    (*pMutexInitFn)(gMutexContext, &globalMutex.fUserMutex, status);
+    globalMutex.fInitialized = TRUE;
+    (*pMutexInitFn)(gMutexContext, &implMutex.fUserMutex, status);
+    implMutex.fInitialized = TRUE;
+}
+
+
+
+/*   synchronized compare and swap function, for use when OS or compiler built-in
+ *   equivalents aren't available.
+ */
+static void *mutexed_compare_and_swap(void **dest, void *newval, void *oldval) {
+    umtx_lock(&implMutex);
+    void *temp = *dest;
+    if (temp == oldval) {
+        *dest = newval;
+    }
+    umtx_unlock(&implMutex);
+    
+    return temp;
+}
+
+
+
+/*-----------------------------------------------------------------
+ *
+ *  Atomic Increment and Decrement
+ *     umtx_atomic_inc
+ *     umtx_atomic_dec
+ *
+ *----------------------------------------------------------------*/
+
+/* Pointers to user-supplied inc/dec functions.  Null if no funcs have been set.  */
+static UMtxAtomicFn  *pIncFn = NULL;
+static UMtxAtomicFn  *pDecFn = NULL;
+static const void *gIncDecContext  = NULL;
+
+#if defined (POSIX) && (U_HAVE_GCC_ATOMICS == 0)
+static UMutex   gIncDecMutex = U_MUTEX_INITIALIZER;
+#endif
+
+U_CAPI int32_t U_EXPORT2
+umtx_atomic_inc(int32_t *p)  {
+    int32_t retVal;
+    if (pIncFn) {
+        retVal = (*pIncFn)(gIncDecContext, p);
+    } else {
+        #if U_PLATFORM_HAS_WIN32_API
+            retVal = InterlockedIncrement((LONG*)p);
+        #elif defined(USE_MAC_OS_ATOMIC_INCREMENT)
+            retVal = OSAtomicIncrement32Barrier(p);
+        #elif (U_HAVE_GCC_ATOMICS == 1)
+            retVal = __sync_add_and_fetch(p, 1);
+        #elif defined (POSIX)
+            umtx_lock(&gIncDecMutex);
+            retVal = ++(*p);
+            umtx_unlock(&gIncDecMutex);
+        #else
+            /* Unknown Platform. */
+            retVal = ++(*p);
+        #endif
+    }
+    return retVal;
+}
+
+U_CAPI int32_t U_EXPORT2
+umtx_atomic_dec(int32_t *p) {
+    int32_t retVal;
+    if (pDecFn) {
+        retVal = (*pDecFn)(gIncDecContext, p);
+    } else {
+        #if U_PLATFORM_HAS_WIN32_API
+            retVal = InterlockedDecrement((LONG*)p);
+        #elif defined(USE_MAC_OS_ATOMIC_INCREMENT)
+            retVal = OSAtomicDecrement32Barrier(p);
+        #elif (U_HAVE_GCC_ATOMICS == 1)
+            retVal = __sync_sub_and_fetch(p, 1);
+        #elif defined (POSIX)
+            umtx_lock(&gIncDecMutex);
+            retVal = --(*p);
+            umtx_unlock(&gIncDecMutex);
+        #else
+            /* Unknown Platform. */
+            retVal = --(*p);
+        #endif
+    }
+    return retVal;
+}
+
+
+
+U_CAPI void U_EXPORT2
+u_setAtomicIncDecFunctions(const void *context, UMtxAtomicFn *ip, UMtxAtomicFn *dp,
+                                UErrorCode *status) {
+    if (U_FAILURE(*status)) {
+        return;
+    }
+    /* Can not set a mutex function to a NULL value  */
+    if (ip==NULL || dp==NULL) {
+        *status = U_ILLEGAL_ARGUMENT_ERROR;
+        return;
+    }
+    /* If ICU is not in an initial state, disallow this operation. */
+    if (cmemory_inUse()) {
+        *status = U_INVALID_STATE_ERROR;
+        return;
+    }
+
+    pIncFn = ip;
+    pDecFn = dp;
+    gIncDecContext = context;
+
+#if U_DEBUG
+    {
+        int32_t   testInt = 0;
+        U_ASSERT(umtx_atomic_inc(&testInt) == 1);     /* Sanity Check.    Do the functions work at all? */
+        U_ASSERT(testInt == 1);
+        U_ASSERT(umtx_atomic_dec(&testInt) == 0);
+        U_ASSERT(testInt == 0);
+    }
+#endif
+}
+
+
+/*
+ *  Mutex Cleanup Function
+ *      Reset the mutex function callback pointers.
+ *      Called from the global ICU u_cleanup() function.
+ */
+U_CFUNC UBool umtx_cleanup(void) {
+    /* Extra, do-nothing function call to suppress compiler warnings on platforms where
+     *   mutexed_compare_and_swap is not otherwise used.  */
+    void *pv = &globalMutex;
+    mutexed_compare_and_swap(&pv, NULL, NULL);
+    usrMutexCleanup();
+           
+    pIncFn          = NULL;
+    pDecFn          = NULL;
+    gIncDecContext  = NULL;
+
+    return TRUE;
+}
index b2ce411d9a1e4994f99f539ef719b72806a93f0f..259cca37fbd0adf131e4ef292bb627c67a807ebc 100644 (file)
 #include "unicode/uclean.h"
 #include "putilimp.h"
 
+/* For _ReadWriteBarrier(). */
 #if defined(_MSC_VER) && _MSC_VER >= 1500
 # include <intrin.h>
 #endif
 
+/* For CRITICAL_SECTION */
+#if U_PLATFORM_HAS_WIN32_API
+#if 0  
+/* TODO(andy): Why doesn't windows.h compile in all files? It does in some.
+ *             The intent was to include windows.h here, and have struct UMutex
+ *             have an embedded CRITICAL_SECTION when building on Windows.
+ *             The workaround is to put some char[] storage in UMutex instead,
+ *             avoiding the need to include windows.h everwhere this header is included.
+ */
+# define WIN32_LEAN_AND_MEAN
+# define VC_EXTRALEAN
+# define NOUSER
+# define NOSERVICE
+# define NOIME
+# define NOMCX
+# include <windows.h>
+#endif  /* 0 */
+#define U_WINDOWS_CRIT_SEC_SIZE 64
+#endif  /* win32 */
+
 #if U_PLATFORM_IS_DARWIN_BASED
 #if defined(__STRICT_ANSI__)
 #define UPRV_REMAP_INLINE
  * an alternative C++ mutex API is defined in the file common/mutex.h
  */
 
+/*
+ * UMutex - Mutexes for use by ICU implementation code.
+ *          Must be declared as static or globals. They cannot appear as members
+ *          of other objects.
+ *          UMutex structs must be initialized.
+ *          Example:
+ *            static UMutex = U_MUTEX_INITIALIZER;
+ *          The declaration of struct UMutex is platform dependent.
+ */
+
+
+#if U_PLATFORM_HAS_WIN32_API
+
+/*  U_INIT_ONCE mimics the windows API INIT_ONCE, which exists on Windows Vista and newer.
+ *  When ICU no longer needs to support older Windows platforms (XP) that do not have
+ * a native INIT_ONCE, switch this implementation over to wrap the native Windows APIs.
+ */
+typedef struct U_INIT_ONCE {
+    long               fState;
+    void              *fContext;
+} U_INIT_ONCE;
+#define U_INIT_ONCE_STATIC_INIT {0, NULL}
+
+typedef struct UMutex {
+    U_INIT_ONCE       fInitOnce;
+    UMTX              fUserMutex;
+    UBool             fInitialized;  /* Applies to fUserMutex only. */
+    /* CRITICAL_SECTION  fCS; */  /* See note above. Unresolved problems with including
+                                   * Windows.h, which would allow using CRITICAL_SECTION
+                                   * directly here. */
+    char              fCS[U_WINDOWS_CRIT_SEC_SIZE];
+} UMutex;
+
+/* Initializer for a static UMUTEX. Deliberately contains no value for the
+ *  CRITICAL_SECTION.
+ */
+#define U_MUTEX_INITIALIZER {U_INIT_ONCE_STATIC_INIT, NULL, FALSE}
+
+#elif U_PLATFORM_IMPLEMENTS_POSIX
+#include <pthread.h>
+
+struct UMutex {
+    pthread_mutex_t  fMutex;
+    UMTX             fUserMutex;
+    UBool            fInitialized;
+};
+#define U_MUTEX_INITIALIZER  {PTHREAD_MUTEX_INITIALIZER, NULL, FALSE}
+
+#else
+/* Unknow platform type. */
+struct UMutex {
+    void *fMutex;
+};
+#define U_MUTEX_INITIALIZER {NULL}
+#error Unknown Platform.
+
+#endif
+
+typedef struct UMutex UMutex;
+    
 /* Lock a mutex.
  * @param mutex The given mutex to be locked.  Pass NULL to specify
  *              the global ICU mutex.  Recursive locks are an error
  *              and may cause a deadlock on some platforms.
  */
-U_CAPI void U_EXPORT2 umtx_lock   ( UMTX* mutex ); 
+U_CAPI void U_EXPORT2 umtx_lock(UMutex* mutex); 
 
-/* Unlock a mutex. Pass in NULL if you want the single global
-   mutex. 
+/* Unlock a mutex.
  * @param mutex The given mutex to be unlocked.  Pass NULL to specify
  *              the global ICU mutex.
  */
-U_CAPI void U_EXPORT2 umtx_unlock ( UMTX* mutex );
-
-/* Initialize a mutex. Use it this way:
-   umtx_init( &aMutex ); 
- * ICU Mutexes do not need explicit initialization before use.  Use of this
- *   function is not necessary.
- * Initialization of an already initialized mutex has no effect, and is safe to do.
- * Initialization of mutexes is thread safe.  Two threads can concurrently 
- *   initialize the same mutex without causing problems.
- * @param mutex The given mutex to be initialized
- */
-U_CAPI void U_EXPORT2 umtx_init   ( UMTX* mutex );
-
-/* Destroy a mutex. This will free the resources of a mutex.
- * Use it this way:
- *   umtx_destroy( &aMutex ); 
- * Destroying an already destroyed mutex has no effect, and causes no problems.
- * This function is not thread safe.  Two threads must not attempt to concurrently
- *   destroy the same mutex.
- * @param mutex The given mutex to be destroyed.
- */
-U_CAPI void U_EXPORT2 umtx_destroy( UMTX *mutex );
+U_CAPI void U_EXPORT2 umtx_unlock (UMutex* mutex);
 
 /*
  * Atomic Increment and Decrement of an int32_t value.
index 64498ecbb21c019a7ecea5435d50ee29a8f579e6..0404e36a821e3b0cd7cda7fbf5cefe2f711e1bb3 100644 (file)
@@ -42,7 +42,7 @@ TODO: This cache should probably be removed when the deprecated code is
 */
 static UHashtable *cache = NULL;
 
-static UMTX resbMutex = NULL;
+static UMutex resbMutex = U_MUTEX_INITIALIZER;
 
 /* INTERNAL: hashes an entry  */
 static int32_t U_CALLCONV hashEntry(const UHashTok parm) {
@@ -260,9 +260,6 @@ static UBool U_CALLCONV ures_cleanup(void)
             cache = NULL;
         }
     }
-    if (cache == NULL && resbMutex != NULL) {
-        umtx_destroy(&resbMutex);
-    }
     return (cache == NULL);
 }
 
index 925ed38b717a334377b7b54df4c2ab9800e0ef28..93832e9652150ca7fb83f79a8a36f2dae796ffae 100644 (file)
@@ -43,7 +43,7 @@ Static cache for already opened StringPrep profiles
 */
 static UHashtable *SHARED_DATA_HASHTABLE = NULL;
 
-static UMTX usprepMutex = NULL;
+static UMutex usprepMutex = U_MUTEX_INITIALIZER;
 
 /* format version of spp file */
 //static uint8_t formatVersion[4]={ 0, 0, 0, 0 };
@@ -196,9 +196,6 @@ static UBool U_CALLCONV usprep_cleanup(void){
         }
     }
 
-    umtx_destroy(&usprepMutex);             /* Don't worry about destroying the mutex even  */
-                                            /*  if the hash table still exists.  The mutex  */
-                                            /*  will lazily re-init  itself if needed.      */
     return (SHARED_DATA_HASHTABLE == NULL);
 }
 U_CDECL_END
index cf51a03fe4e90135fcba16ee3970064456e0c4ec..93f1a7174bcdd8801ccf2d1317d906138ab4d330 100644 (file)
@@ -653,7 +653,7 @@ const UnicodeString *AlphabeticIndex::EMPTY_STRING;
 //                  sufficiently heavy that the cost of the mutex check is not significant.
 
 void AlphabeticIndex::staticInit(UErrorCode &status) {
-    static UMTX IndexCharsInitMutex;
+    static UMutex IndexCharsInitMutex = U_MUTEX_INITIALIZER;
 
     Mutex mutex(&IndexCharsInitMutex);
     if (indexCharactersAreInitialized || U_FAILURE(status)) {
index f4ea55e146a358ced18719205ffed24414666156..dfbe9fadc21c3f5623ab3a12d14c7a8a31f96dd8 100644 (file)
@@ -1,5 +1,5 @@
 /************************************************************************
- * Copyright (C) 1996-2011, International Business Machines Corporation
+ * Copyright (C) 1996-2012, International Business Machines Corporation
  * and others. All Rights Reserved.
  ************************************************************************
  *  2003-nov-07   srl       Port from Java
@@ -63,11 +63,10 @@ static inline UBool isINVALID(double d) {
   return(uprv_isNaN(d));
 }
 
-static UMTX ccLock = NULL;
+static UMutex ccLock = U_MUTEX_INITIALIZER;
 
 U_CDECL_BEGIN
 static UBool calendar_astro_cleanup(void) {
-  umtx_destroy(&ccLock);
   return TRUE;
 }
 U_CDECL_END
index 2d67c68357626650c863a21afd225b83f271d79e..9c9dc79dd24b6d0bc0a82d2155a99d8823b08d86 100644 (file)
@@ -1,6 +1,6 @@
 /*
  ******************************************************************************
- * Copyright (C) 2007-2011, International Business Machines Corporation
+ * Copyright (C) 2007-2012, International Business Machines Corporation
  * and others. All Rights Reserved.
  ******************************************************************************
  *
@@ -48,7 +48,7 @@ static void debug_chnsecal_msg(const char *pat, ...)
 
 
 // --- The cache --
-static UMTX astroLock = 0;  // pod bay door lock
+static UMutex astroLock = U_MUTEX_INITIALIZER;  // pod bay door lock
 static icu::CalendarAstronomer *gChineseCalendarAstro = NULL;
 static icu::CalendarCache *gChineseCalendarWinterSolsticeCache = NULL;
 static icu::CalendarCache *gChineseCalendarNewYearCache = NULL;
@@ -90,7 +90,6 @@ static UBool calendar_chinese_cleanup(void) {
         delete gChineseCalendarNewYearCache;
         gChineseCalendarNewYearCache = NULL;
     }
-    umtx_destroy(&astroLock);
     return TRUE;
 }
 U_CDECL_END
index a488ea07726a8b048f898ee67addd5af6a2fcf98..875aa9da52be574d35b6c9eb3319c7d4376aefad 100644 (file)
@@ -480,7 +480,7 @@ private:
 
     UHashtable *cache;
 };
-static UMTX lock;
+static UMutex lock = U_MUTEX_INITIALIZER;
 
 U_CDECL_BEGIN
 static void U_CALLCONV
index e0a9165d1534bb8002c2e257065ebf3366869087..77d8d0527f10d166bd434cecbfc89d348c4a5f9f 100644 (file)
@@ -177,7 +177,7 @@ static const char gQuartersTag[]="quarters";
 
 static const char gContextTransformsTag[]="contextTransforms";
 
-static UMTX LOCK;
+static UMutex LOCK = U_MUTEX_INITIALIZER;
 
 /**
  * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly.
index 051c345086b6a26f01912487b62bdaea9464b25d..1e60fcb05f6c0cf6e206948000686e6b2f1b6b49 100644 (file)
@@ -28,7 +28,7 @@
 #include "uhash.h"
 
 static UHashtable* gGenderInfoCache = NULL;
-static UMTX gGenderMetaLock = NULL;
+static UMutex gGenderMetaLock = U_MUTEX_INITIALIZER;
 static const char* gNeutralStr = "neutral";
 static const char* gMailTaintsStr = "maleTaints";
 static const char* gMixedNeutralStr = "mixedNeutral";
@@ -44,7 +44,6 @@ enum GenderStyle {
 U_CDECL_BEGIN
 
 static UBool U_CALLCONV gender_cleanup(void) {
-  umtx_destroy(&gGenderMetaLock);
   if (gGenderInfoCache != NULL) {
     uhash_close(gGenderInfoCache);
     gGenderInfoCache = NULL;
index 968c88ab661044e00816b1638d5e4189801b982d..6d553787da3b188f97681b6c1a247c55b5a57ff0 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ******************************************************************************
-* Copyright (C) 2003-2011, International Business Machines Corporation
+* Copyright (C) 2003-2012, International Business Machines Corporation
 * and others. All Rights Reserved.
 ******************************************************************************
 *
@@ -51,7 +51,7 @@ static void debug_islamcal_msg(const char *pat, ...)
 
 // --- The cache --
 // cache of months
-static UMTX astroLock = 0;  // pod bay door lock
+static UMutex astroLock = U_MUTEX_INITIALIZER;  // pod bay door lock
 static icu::CalendarCache *gMonthCache = NULL;
 static icu::CalendarAstronomer *gIslamicCalendarAstro = NULL;
 
@@ -65,7 +65,6 @@ static UBool calendar_islamic_cleanup(void) {
         delete gIslamicCalendarAstro;
         gIslamicCalendarAstro = NULL;
     }
-    umtx_destroy(&astroLock);
     return TRUE;
 }
 U_CDECL_END
index 161559ace001afd861d5960342932dbd73d99f83..6b4fd06d9c1c735949c5bdd0ac1854edfac66549 100644 (file)
@@ -139,7 +139,7 @@ static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = {
 // Static hashtable cache of NumberingSystem objects used by NumberFormat
 static UHashtable * NumberingSystem_cache = NULL;
 
-static UMTX nscacheMutex = NULL;
+static UMutex nscacheMutex = U_MUTEX_INITIALIZER;
 
 #if !UCONFIG_NO_SERVICE
 static icu::ICULocaleService* gService = NULL;
index 2f80a54ec439335a79c5725e41dadc09fd3fcae7..2ceb511f488da2204514c3c34b9c21c6e9cb82c0 100644 (file)
@@ -29,7 +29,7 @@
 U_NAMESPACE_BEGIN
 
 // shared by all instances when lazy-initializing samples
-static UMTX pluralMutex;
+static UMutex pluralMutex = U_MUTEX_INITIALIZER;
 
 #define ARRAY_SIZE(array) (int32_t)(sizeof array  / sizeof array[0])
 
index 6041a9245e654f25daab0936cc8b193c1570218d..b987ade2c7257b0af0b7839ae8e93a29b24345da 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (C) 1999-2008, International Business Machines
+*   Copyright (C) 1999-2012, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -24,7 +24,7 @@ U_NAMESPACE_BEGIN
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTransliterator)
 
-static UMTX  transliteratorDataMutex = NULL;
+static UMutex transliteratorDataMutex = U_MUTEX_INITIALIZER;
 static Replaceable *gLockedText = NULL;
 
 void RuleBasedTransliterator::_construct(const UnicodeString& rules,
index f5daecf4778ff83e09786ee52fa52378d396820e..6af257d64d21c4eb6bca15ee1b6be18c949fd8c7 100644 (file)
@@ -209,8 +209,7 @@ static const int32_t gFieldRangeBias[] = {
 static const int32_t HEBREW_CAL_CUR_MILLENIUM_START_YEAR = 5000;
 static const int32_t HEBREW_CAL_CUR_MILLENIUM_END_YEAR = 6000;
 
-
-static UMTX LOCK;
+static UMutex LOCK = U_MUTEX_INITIALIZER;
 
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat)
 
index 7c85b8ed9dbbf3adcebd9113677a84e4b86c400c..ca98ef30bd086433e2988eb08aba200535d3d9a7 100644 (file)
@@ -109,8 +109,8 @@ static const UChar         UNKNOWN_ZONE_ID[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x
 static const int32_t       GMT_ID_LENGTH = 3;
 static const int32_t       UNKNOWN_ZONE_ID_LENGTH = 11;
 
-static UMTX LOCK;
-static UMTX TZSET_LOCK;
+static UMutex LOCK = U_MUTEX_INITIALIZER;
+static UMutex TZSET_LOCK = U_MUTEX_INITIALIZER;
 static icu::TimeZone* DEFAULT_ZONE = NULL;
 static icu::TimeZone* _GMT = NULL;
 static icu::TimeZone* _UNKNOWN_ZONE = NULL;
@@ -153,15 +153,6 @@ static UBool U_CALLCONV timeZone_cleanup(void)
     uprv_free(MAP_CANONICAL_SYSTEM_LOCATION_ZONES);
     MAP_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
 
-    if (LOCK) {
-        umtx_destroy(&LOCK);
-        LOCK = NULL;
-    }
-    if (TZSET_LOCK) {
-        umtx_destroy(&TZSET_LOCK);
-        TZSET_LOCK = NULL;
-    }
-
     return TRUE;
 }
 U_CDECL_END
index e82cd59b0ab3b3ca99ccb45479668f9df365e5fd..bb9ba9b19039564fb0a520c1494e674ae46f92cf 100644 (file)
@@ -89,7 +89,7 @@ static const char RB_RULE_BASED_IDS[] = "RuleBasedTransliteratorIDs";
 /**
  * The mutex controlling access to registry object.
  */
-static UMTX registryMutex = 0;
+static UMutex registryMutex = U_MUTEX_INITIALIZER;
 
 /**
  * System transliterator registry; non-null when initialized.
@@ -1633,7 +1633,6 @@ U_CFUNC UBool utrans_transliterator_cleanup(void) {
         delete registry;
         registry = NULL;
     }
-    umtx_destroy(&registryMutex);
     return TRUE;
 }
 
index b195e5234ede8d102e18f16c7b52983fcb61db72..37a7adeff156b290b7ef469d95f707f52a869559 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002-2011, International Business Machines Corporation
+*   Copyright (c) 2002-2012, International Business Machines Corporation
 *   and others.  All Rights Reserved.
 **********************************************************************
 *   Date        Name        Description
@@ -45,7 +45,7 @@ static Hashtable* SPECIAL_INVERSES = NULL;
 /**
  * The mutex controlling access to SPECIAL_INVERSES
  */
-static UMTX LOCK = 0;
+static UMutex LOCK = U_MUTEX_INITIALIZER;
 
 TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString& t,
                                      const UnicodeString& v, UBool sawS,
@@ -928,7 +928,6 @@ void TransliteratorIDParser::cleanup() {
         delete SPECIAL_INVERSES;
         SPECIAL_INVERSES = NULL;
     }
-    umtx_destroy(&LOCK);
 }
 
 U_NAMESPACE_END
index a86174559249bc73f65c74e46e5be8bc2c708944..2c694760b9d3eb6b89721d3ba99ba9e21678f225 100644 (file)
@@ -243,7 +243,7 @@ U_CDECL_END
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeZoneFormat)
 
 TimeZoneFormat::TimeZoneFormat(const Locale& locale, UErrorCode& status) 
-: fLock(NULL),fLocale(locale), fTimeZoneNames(NULL), fTimeZoneGenericNames(NULL), fDefParseOptionFlags(0) {
+: fLocale(locale), fTimeZoneNames(NULL), fTimeZoneGenericNames(NULL), fDefParseOptionFlags(0) {
 
     for (int32_t i = 0; i <= UTZFMT_PAT_NEGATIVE_HMS; i++) {
         fGMTOffsetPatternItems[i] = NULL;
@@ -346,7 +346,6 @@ TimeZoneFormat::~TimeZoneFormat() {
     for (int32_t i = 0; i <= UTZFMT_PAT_NEGATIVE_HMS; i++) {
         delete fGMTOffsetPatternItems[i];
     }
-    umtx_destroy(&fLock);
 }
 
 TimeZoneFormat&
@@ -1005,6 +1004,8 @@ TimeZoneFormat::formatSpecific(const TimeZone& tz, UTimeZoneNameType stdType, UT
     return name;
 }
 
+static UMutex gLock = U_MUTEX_INITIALIZER;
+
 const TimeZoneGenericNames*
 TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
     if (U_FAILURE(status)) {
@@ -1015,13 +1016,13 @@ TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
     UMTX_CHECK(&gZoneMetaLock, (fTimeZoneGenericNames == NULL), create);
     if (create) {
         TimeZoneFormat *nonConstThis = const_cast<TimeZoneFormat *>(this);
-        umtx_lock(&nonConstThis->fLock);
+        umtx_lock(&gLock);
         {
             if (fTimeZoneGenericNames == NULL) {
                 nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status);
             }
         }
-        umtx_unlock(&nonConstThis->fLock);
+        umtx_unlock(&gLock);
     }
 
     return fTimeZoneGenericNames;
index 0b1d4b4ef4f1e3684054a4a6a45258482eb3330d..15fbf950a2c2a9207c223911b2f1d3a850304bbc 100644 (file)
@@ -267,6 +267,8 @@ GNameSearchHandler::getMatches(int32_t& maxMatchLen) {
     return results;
 }
 
+static UMutex gLock = U_MUTEX_INITIALIZER;
+
 class TZGNCore : public UMemory {
 public:
     TZGNCore(const Locale& locale, UErrorCode& status);
@@ -282,7 +284,6 @@ public:
 
 private:
     Locale fLocale;
-    UMTX fLock;
     const TimeZoneNames* fTimeZoneNames;
     UHashtable* fLocationNamesMap;
     UHashtable* fPartialLocationNamesMap;
@@ -330,7 +331,6 @@ private:
 // ---------------------------------------------------
 TZGNCore::TZGNCore(const Locale& locale, UErrorCode& status)
 : fLocale(locale),
-  fLock(NULL),
   fTimeZoneNames(NULL),
   fLocationNamesMap(NULL),
   fPartialLocationNamesMap(NULL),
@@ -345,7 +345,6 @@ TZGNCore::TZGNCore(const Locale& locale, UErrorCode& status)
 
 TZGNCore::~TZGNCore() {
     cleanup();
-    umtx_destroy(&fLock);
 }
 
 void
@@ -504,11 +503,11 @@ TZGNCore::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeStri
 
     const UChar *locname = NULL;
     TZGNCore *nonConstThis = const_cast<TZGNCore *>(this);
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         locname = nonConstThis->getGenericLocationName(tzCanonicalID);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (locname == NULL) {
         name.setToBogus();
@@ -769,11 +768,11 @@ TZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID,
 
     const UChar *uplname = NULL;
     TZGNCore *nonConstThis = const_cast<TZGNCore *>(this);
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         uplname = nonConstThis->getPartialLocationName(tzCanonicalID, mzID, isLong, mzDisplayName);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (uplname == NULL) {
         name.setToBogus();
@@ -1042,11 +1041,11 @@ TZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UE
 
     TZGNCore *nonConstThis = const_cast<TZGNCore *>(this);
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (U_FAILURE(status)) {
         return NULL;
@@ -1073,7 +1072,7 @@ TZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UE
 
     // All names are not yet loaded into the local trie.
     // Load all available names into the trie. This could be very heavy.
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         if (!fGNamesTrieFullyLoaded) {
             StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
@@ -1095,18 +1094,18 @@ TZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UE
             }
         }
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (U_FAILURE(status)) {
         return NULL;
     }
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         // now try it again
         fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     results = handler.getMatches(maxLen);
     if (results != NULL && maxLen > 0) {
@@ -1147,7 +1146,7 @@ typedef struct TZGNCoreRef {
 } TZGNCoreRef;
 
 // TZGNCore object cache handling
-static UMTX gTZGNLock = NULL;
+static UMutex gTZGNLock = U_MUTEX_INITIALIZER;
 static UHashtable *gTZGNCoreCache = NULL;
 static UBool gTZGNCoreCacheInitialized = FALSE;
 
@@ -1170,8 +1169,6 @@ U_CDECL_BEGIN
  */
 static UBool U_CALLCONV tzgnCore_cleanup(void)
 {
-    umtx_destroy(&gTZGNLock);
-
     if (gTZGNCoreCache != NULL) {
         uhash_close(gTZGNCoreCache);
         gTZGNCoreCache = NULL;
index 55ee4168b77f545c8197135965613ffcd0b473bf..b7fc35c20b08a76d2ac4bdbe7bbe7e998259b9b9 100644 (file)
@@ -33,7 +33,7 @@ static const UChar gRiyadh8[]           = { 0x52, 0x69, 0x79, 0x61, 0x64, 0x68,
 static const int32_t gRiyadh8Len       = 7;
 
 // TimeZoneNames object cache handling
-static UMTX gTimeZoneNamesLock = NULL;
+static UMutex gTimeZoneNamesLock = U_MUTEX_INITIALIZER;
 static UHashtable *gTimeZoneNamesCache = NULL;
 static UBool gTimeZoneNamesCacheInitialized = FALSE;
 
@@ -62,8 +62,6 @@ U_CDECL_BEGIN
  */
 static UBool U_CALLCONV timeZoneNames_cleanup(void)
 {
-    umtx_destroy(&gTimeZoneNamesLock);
-
     if (gTimeZoneNamesCache != NULL) {
         uhash_close(gTimeZoneNamesCache);
         gTimeZoneNamesCache = NULL;
index a699ec8c0b4ead79e2d7735aa72feae60c4d2446..876411bc599fb8a7ef68efa704460e12c908c63f 100644 (file)
@@ -282,7 +282,7 @@ TextTrieMap::getChildNode(CharacterNode *parent, UChar c) const {
 }
 
 // Mutex for protecting the lazy creation of the Trie node structure on the first call to search().
-static UMTX TextTrieMutex;
+static UMutex TextTrieMutex = U_MUTEX_INITIALIZER;
 
 // buildTrie() - The Trie node structure is needed.  Create it from the data that was
 //               saved at the time the ZoneStringFormatter was created.  The Trie is only
@@ -837,9 +837,10 @@ deleteZNameInfo(void *obj) {
 
 U_CDECL_END
 
+static UMutex gLock = U_MUTEX_INITIALIZER;
+
 TimeZoneNamesImpl::TimeZoneNamesImpl(const Locale& locale, UErrorCode& status)
 : fLocale(locale),
-  fLock(NULL),
   fZoneStrings(NULL),
   fTZNamesMap(NULL),
   fMZNamesMap(NULL),
@@ -911,7 +912,6 @@ TimeZoneNamesImpl::loadStrings(const UnicodeString& tzCanonicalID) {
 
 TimeZoneNamesImpl::~TimeZoneNamesImpl() {
     cleanup();
-    umtx_destroy(&fLock);
 }
 
 void
@@ -1015,11 +1015,11 @@ TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
     ZNames *znames = NULL;
     TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         znames = nonConstThis->loadMetaZoneNames(mzID);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (znames != NULL) {
         const UChar* s = znames->getName(type);
@@ -1040,11 +1040,11 @@ TimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNa
     TZNames *tznames = NULL;
     TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         tznames = nonConstThis->loadTimeZoneNames(tzID);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (tznames != NULL) {
         const UChar *s = tznames->getName(type);
@@ -1061,11 +1061,11 @@ TimeZoneNamesImpl::getExemplarLocationName(const UnicodeString& tzID, UnicodeStr
     TZNames *tznames = NULL;
     TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         tznames = nonConstThis->loadTimeZoneNames(tzID);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (tznames != NULL) {
         locName = tznames->getLocationName();
@@ -1246,11 +1246,11 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types
 
     TimeZoneNamesImpl *nonConstThis = const_cast<TimeZoneNamesImpl *>(this);
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (U_FAILURE(status)) {
         return NULL;
@@ -1266,7 +1266,7 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types
     delete matches;
 
     // All names are not yet loaded into the trie
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         if (!fNamesTrieFullyLoaded) {
             const UnicodeString *id;
@@ -1290,18 +1290,18 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types
             }
         }
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     if (U_FAILURE(status)) {
         return NULL;
     }
 
-    umtx_lock(&nonConstThis->fLock);
+    umtx_lock(&gLock);
     {
         // now try it again
         fNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
     }
-    umtx_unlock(&nonConstThis->fLock);
+    umtx_unlock(&gLock);
 
     return handler.getMatches(maxLen);
 }
index 1e64710bebbfa77ef8cbed73d1e49a8c85c00607..c03eb8e6ed4ecc640f9bf3d3d029c5f7b47298b5 100644 (file)
@@ -187,7 +187,6 @@ public:
 private:
 
     Locale fLocale;
-    UMTX fLock;
 
     UResourceBundle* fZoneStrings;
 
index b86f8e288c6989a3d443c6024dcb2f4197593ca5..ed6c53f99fc42ab91ad46fe91a920d84dd1bb879 100644 (file)
@@ -102,7 +102,7 @@ static const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0};
 static UHashtable* gIsoCodes = NULL;
 static UBool gIsoCodesInitialized = FALSE;
 
-static UMTX gIsoCodesLock = NULL;
+static UMutex gIsoCodesLock = U_MUTEX_INITIALIZER;
 
 //------------------------------------------------------------
 // Code
@@ -113,10 +113,6 @@ static UMTX gIsoCodesLock = NULL;
 static UBool U_CALLCONV 
 isoCodes_cleanup(void)
 {
-    if (gIsoCodesLock != NULL) {
-        umtx_destroy(&gIsoCodesLock);
-    }
-
     if (gIsoCodes != NULL) {
         uhash_close(gIsoCodes);
         gIsoCodes = NULL;
@@ -249,7 +245,7 @@ U_CDECL_END
 #if !UCONFIG_NO_SERVICE
 struct CReg;
 
-static UMTX gCRegLock = 0;
+static UMutex gCRegLock = U_MUTEX_INITIALIZER;
 static CReg* gCRegHead = 0;
 
 struct CReg : public icu::UMemory {
@@ -334,7 +330,6 @@ struct CReg : public icu::UMemory {
             gCRegHead = gCRegHead->next;
             delete n;
         }
-        umtx_destroy(&gCRegLock);
     }
 };
 
index 090d8d70ae4bad0cb7400640f506c03ebde80e31..8a68ca191704bb5979de26f12612027b6c9770af 100644 (file)
@@ -141,8 +141,6 @@ typedef enum UTimeZoneFormatParseOption {
 
 U_CDECL_END
 
-typedef void *UMTX;
-
 U_NAMESPACE_BEGIN
 
 class TimeZoneGenericNames;
@@ -528,9 +526,6 @@ protected:
     TimeZoneFormat(const Locale& locale, UErrorCode& status);
 
 private:
-    /* mutex */
-    UMTX fLock;
-
     /* Locale of this object */
     Locale fLocale;
 
index e244f9c2f82463cb504e303fb1becd22c81fc552..932c5ab678c0f8b70496dbc39b634e9f531e53b1 100644 (file)
@@ -27,7 +27,7 @@
 #include "uhash.h"
 #include "olsontz.h"
 
-static UMTX gZoneMetaLock = NULL;
+static UMutex gZoneMetaLock = U_MUTEX_INITIALIZER;
 
 // CLDR Canonical ID mapping table
 static UHashtable *gCanonicalIDCache = NULL;
@@ -54,8 +54,6 @@ U_CDECL_BEGIN
  */
 static UBool U_CALLCONV zoneMeta_cleanup(void)
 {
-    umtx_destroy(&gZoneMetaLock);
-
     if (gCanonicalIDCache != NULL) {
         uhash_close(gCanonicalIDCache);
         gCanonicalIDCache = NULL;
index 2b8260587368879626b6ae54c886acfe2b29e814..fc6a6607ed3806e96584c642fdaaafc53429d5de 100644 (file)
@@ -446,8 +446,8 @@ void MultithreadTest::TestArabicShapingThreads()
 //               platform's mutex support is at least superficially there.
 //
 //----------------------------------------------------------------------
-static UMTX    gTestMutexA = NULL;
-static UMTX    gTestMutexB = NULL;
+static UMutex    gTestMutexA = U_MUTEX_INITIALIZER;
+static UMutex    gTestMutexB = U_MUTEX_INITIALIZER;
 
 static int     gThreadsStarted = 0; 
 static int     gThreadsInMiddle = 0;
@@ -550,11 +550,6 @@ void MultithreadTest::TestMutex()
     }
 
     // All threads made it by both mutexes.
-    // Destroy the test mutexes.
-    umtx_destroy(&gTestMutexA);
-    umtx_destroy(&gTestMutexB);
-    gTestMutexA=NULL;
-    gTestMutexB=NULL;
 
     for (i=0; i<TESTMUTEX_THREAD_COUNT; i++) {
         delete threads[i];