diff --git a/icu4c/source/common/common.vcxproj b/icu4c/source/common/common.vcxproj
index c62a1a8e957..9d708136d7d 100644
--- a/icu4c/source/common/common.vcxproj
+++ b/icu4c/source/common/common.vcxproj
@@ -286,7 +286,7 @@
false
-
+
false
false
false
diff --git a/icu4c/source/common/common.vcxproj.filters b/icu4c/source/common/common.vcxproj.filters
index b87cefcf978..01b23c4e3b5 100644
--- a/icu4c/source/common/common.vcxproj.filters
+++ b/icu4c/source/common/common.vcxproj.filters
@@ -163,7 +163,7 @@
configuration
-
+
configuration
diff --git a/icu4c/source/common/listformatter.cpp b/icu4c/source/common/listformatter.cpp
index 31c46484a2a..6a6e986377d 100644
--- a/icu4c/source/common/listformatter.cpp
+++ b/icu4c/source/common/listformatter.cpp
@@ -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}"
diff --git a/icu4c/source/common/mutex.h b/icu4c/source/common/mutex.h
index 7f7ef897afa..af8cd8cb9c2 100644
--- a/icu4c/source/common/mutex.h
+++ b/icu4c/source/common/mutex.h
@@ -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);
diff --git a/icu4c/source/common/putil.cpp b/icu4c/source/common/putil.cpp
index 9946d8e1b65..4694aa9a806 100644
--- a/icu4c/source/common/putil.cpp
+++ b/icu4c/source/common/putil.cpp
@@ -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;
diff --git a/icu4c/source/common/serv.cpp b/icu4c/source/common/serv.cpp
index 2cddcfe65dc..1a8c9166e04 100644
--- a/icu4c/source/common/serv.cpp
+++ b/icu4c/source/common/serv.cpp
@@ -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;
};
diff --git a/icu4c/source/common/servls.cpp b/icu4c/source/common/servls.cpp
index 0e29bfcee6f..418be4a5d94 100644
--- a/icu4c/source/common/servls.cpp
+++ b/icu4c/source/common/servls.cpp
@@ -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())
{
diff --git a/icu4c/source/common/servnotf.cpp b/icu4c/source/common/servnotf.cpp
index feecbc31dd2..dbcbe92df80 100644
--- a/icu4c/source/common/servnotf.cpp
+++ b/icu4c/source/common/servnotf.cpp
@@ -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)
diff --git a/icu4c/source/common/ubidi_props.c b/icu4c/source/common/ubidi_props.c
index 6fca5a34074..e6f197431d2 100644
--- a/icu4c/source/common/ubidi_props.c
+++ b/icu4c/source/common/ubidi_props.c
@@ -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"
diff --git a/icu4c/source/common/uchar.c b/icu4c/source/common/uchar.c
index d8520e21629..53f92ffd6be 100644
--- a/icu4c/source/common/uchar.c
+++ b/icu4c/source/common/uchar.c
@@ -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"
diff --git a/icu4c/source/common/ucln.h b/icu4c/source/common/ucln.h
index 47f082a154e..2a83d9467ec 100644
--- a/icu4c/source/common/ucln.h
+++ b/icu4c/source/common/ucln.h
@@ -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
diff --git a/icu4c/source/common/ucln_cmn.c b/icu4c/source/common/ucln_cmn.c
index a7776ba4a6f..513d796e581 100644
--- a/icu4c/source/common/ucln_cmn.c
+++ b/icu4c/source/common/ucln_cmn.c
@@ -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;
diff --git a/icu4c/source/common/ucnv_bld.cpp b/icu4c/source/common/ucnv_bld.cpp
index 02159f97d0e..9532620c57d 100644
--- a/icu4c/source/common/ucnv_bld.cpp
+++ b/icu4c/source/common/ucnv_bld.cpp
@@ -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);
}
diff --git a/icu4c/source/common/ucnvmbcs.c b/icu4c/source/common/ucnvmbcs.c
index f3d83a3625e..f88adf1d8d5 100644
--- a/icu4c/source/common/ucnvmbcs.c
+++ b/icu4c/source/common/ucnvmbcs.c
@@ -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
diff --git a/icu4c/source/common/udata.cpp b/icu4c/source/common/udata.cpp
index c4f8752a4eb..0837893eeb0 100644
--- a/icu4c/source/common/udata.cpp
+++ b/icu4c/source/common/udata.cpp
@@ -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) {
diff --git a/icu4c/source/common/uinit.c b/icu4c/source/common/uinit.c
index 44d496acbd4..db3f252c5fb 100644
--- a/icu4c/source/common/uinit.c
+++ b/icu4c/source/common/uinit.c
@@ -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
index e36c241adc6..00000000000
--- a/icu4c/source/common/umutex.c
+++ /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 /* 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
-#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
index 00000000000..a7299a5cfd1
--- /dev/null
+++ b/icu4c/source/common/umutex.cpp
@@ -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 /* 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
+#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(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;
+}
diff --git a/icu4c/source/common/umutex.h b/icu4c/source/common/umutex.h
index b2ce411d9a1..259cca37fbd 100644
--- a/icu4c/source/common/umutex.h
+++ b/icu4c/source/common/umutex.h
@@ -22,10 +22,31 @@
#include "unicode/uclean.h"
#include "putilimp.h"
+/* For _ReadWriteBarrier(). */
#if defined(_MSC_VER) && _MSC_VER >= 1500
# include
#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
+#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
@@ -117,40 +138,78 @@
* 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
+
+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.
diff --git a/icu4c/source/common/uresbund.cpp b/icu4c/source/common/uresbund.cpp
index 64498ecbb21..0404e36a821 100644
--- a/icu4c/source/common/uresbund.cpp
+++ b/icu4c/source/common/uresbund.cpp
@@ -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);
}
diff --git a/icu4c/source/common/usprep.cpp b/icu4c/source/common/usprep.cpp
index 925ed38b717..93832e96521 100644
--- a/icu4c/source/common/usprep.cpp
+++ b/icu4c/source/common/usprep.cpp
@@ -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
diff --git a/icu4c/source/i18n/alphaindex.cpp b/icu4c/source/i18n/alphaindex.cpp
index cf51a03fe4e..93f1a7174bc 100644
--- a/icu4c/source/i18n/alphaindex.cpp
+++ b/icu4c/source/i18n/alphaindex.cpp
@@ -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)) {
diff --git a/icu4c/source/i18n/astro.cpp b/icu4c/source/i18n/astro.cpp
index f4ea55e146a..dfbe9fadc21 100644
--- a/icu4c/source/i18n/astro.cpp
+++ b/icu4c/source/i18n/astro.cpp
@@ -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
diff --git a/icu4c/source/i18n/chnsecal.cpp b/icu4c/source/i18n/chnsecal.cpp
index 2d67c683576..9c9dc79dd24 100644
--- a/icu4c/source/i18n/chnsecal.cpp
+++ b/icu4c/source/i18n/chnsecal.cpp
@@ -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
diff --git a/icu4c/source/i18n/colldata.cpp b/icu4c/source/i18n/colldata.cpp
index a488ea07726..875aa9da52b 100644
--- a/icu4c/source/i18n/colldata.cpp
+++ b/icu4c/source/i18n/colldata.cpp
@@ -480,7 +480,7 @@ private:
UHashtable *cache;
};
-static UMTX lock;
+static UMutex lock = U_MUTEX_INITIALIZER;
U_CDECL_BEGIN
static void U_CALLCONV
diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp
index e0a9165d153..77d8d0527f1 100644
--- a/icu4c/source/i18n/dtfmtsym.cpp
+++ b/icu4c/source/i18n/dtfmtsym.cpp
@@ -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.
diff --git a/icu4c/source/i18n/gender.cpp b/icu4c/source/i18n/gender.cpp
index 051c345086b..1e60fcb05f6 100644
--- a/icu4c/source/i18n/gender.cpp
+++ b/icu4c/source/i18n/gender.cpp
@@ -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;
diff --git a/icu4c/source/i18n/islamcal.cpp b/icu4c/source/i18n/islamcal.cpp
index 968c88ab661..6d553787da3 100644
--- a/icu4c/source/i18n/islamcal.cpp
+++ b/icu4c/source/i18n/islamcal.cpp
@@ -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
diff --git a/icu4c/source/i18n/numfmt.cpp b/icu4c/source/i18n/numfmt.cpp
index 161559ace00..6b4fd06d9c1 100644
--- a/icu4c/source/i18n/numfmt.cpp
+++ b/icu4c/source/i18n/numfmt.cpp
@@ -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;
diff --git a/icu4c/source/i18n/plurrule.cpp b/icu4c/source/i18n/plurrule.cpp
index 2f80a54ec43..2ceb511f488 100644
--- a/icu4c/source/i18n/plurrule.cpp
+++ b/icu4c/source/i18n/plurrule.cpp
@@ -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])
diff --git a/icu4c/source/i18n/rbt.cpp b/icu4c/source/i18n/rbt.cpp
index 6041a9245e6..b987ade2c72 100644
--- a/icu4c/source/i18n/rbt.cpp
+++ b/icu4c/source/i18n/rbt.cpp
@@ -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,
diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp
index f5daecf4778..6af257d64d2 100644
--- a/icu4c/source/i18n/smpdtfmt.cpp
+++ b/icu4c/source/i18n/smpdtfmt.cpp
@@ -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)
diff --git a/icu4c/source/i18n/timezone.cpp b/icu4c/source/i18n/timezone.cpp
index 7c85b8ed9db..ca98ef30bd0 100644
--- a/icu4c/source/i18n/timezone.cpp
+++ b/icu4c/source/i18n/timezone.cpp
@@ -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
diff --git a/icu4c/source/i18n/translit.cpp b/icu4c/source/i18n/translit.cpp
index e82cd59b0ab..bb9ba9b1903 100644
--- a/icu4c/source/i18n/translit.cpp
+++ b/icu4c/source/i18n/translit.cpp
@@ -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(®istryMutex);
return TRUE;
}
diff --git a/icu4c/source/i18n/tridpars.cpp b/icu4c/source/i18n/tridpars.cpp
index b195e5234ed..37a7adeff15 100644
--- a/icu4c/source/i18n/tridpars.cpp
+++ b/icu4c/source/i18n/tridpars.cpp
@@ -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
diff --git a/icu4c/source/i18n/tzfmt.cpp b/icu4c/source/i18n/tzfmt.cpp
index a8617455924..2c694760b9d 100644
--- a/icu4c/source/i18n/tzfmt.cpp
+++ b/icu4c/source/i18n/tzfmt.cpp
@@ -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(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;
diff --git a/icu4c/source/i18n/tzgnames.cpp b/icu4c/source/i18n/tzgnames.cpp
index 0b1d4b4ef4f..15fbf950a2c 100644
--- a/icu4c/source/i18n/tzgnames.cpp
+++ b/icu4c/source/i18n/tzgnames.cpp
@@ -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(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(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(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;
diff --git a/icu4c/source/i18n/tznames.cpp b/icu4c/source/i18n/tznames.cpp
index 55ee4168b77..b7fc35c20b0 100644
--- a/icu4c/source/i18n/tznames.cpp
+++ b/icu4c/source/i18n/tznames.cpp
@@ -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;
diff --git a/icu4c/source/i18n/tznames_impl.cpp b/icu4c/source/i18n/tznames_impl.cpp
index a699ec8c0b4..876411bc599 100644
--- a/icu4c/source/i18n/tznames_impl.cpp
+++ b/icu4c/source/i18n/tznames_impl.cpp
@@ -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(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(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(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(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);
}
diff --git a/icu4c/source/i18n/tznames_impl.h b/icu4c/source/i18n/tznames_impl.h
index 1e64710bebb..c03eb8e6ed4 100644
--- a/icu4c/source/i18n/tznames_impl.h
+++ b/icu4c/source/i18n/tznames_impl.h
@@ -187,7 +187,6 @@ public:
private:
Locale fLocale;
- UMTX fLock;
UResourceBundle* fZoneStrings;
diff --git a/icu4c/source/i18n/ucurr.cpp b/icu4c/source/i18n/ucurr.cpp
index b86f8e288c6..ed6c53f99fc 100644
--- a/icu4c/source/i18n/ucurr.cpp
+++ b/icu4c/source/i18n/ucurr.cpp
@@ -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);
}
};
diff --git a/icu4c/source/i18n/unicode/tzfmt.h b/icu4c/source/i18n/unicode/tzfmt.h
index 090d8d70ae4..8a68ca19170 100644
--- a/icu4c/source/i18n/unicode/tzfmt.h
+++ b/icu4c/source/i18n/unicode/tzfmt.h
@@ -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;
diff --git a/icu4c/source/i18n/zonemeta.cpp b/icu4c/source/i18n/zonemeta.cpp
index e244f9c2f82..932c5ab678c 100644
--- a/icu4c/source/i18n/zonemeta.cpp
+++ b/icu4c/source/i18n/zonemeta.cpp
@@ -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;
diff --git a/icu4c/source/test/intltest/tsmthred.cpp b/icu4c/source/test/intltest/tsmthred.cpp
index 2b826058736..fc6a6607ed3 100644
--- a/icu4c/source/test/intltest/tsmthred.cpp
+++ b/icu4c/source/test/intltest/tsmthred.cpp
@@ -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