<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
<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
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}"
/*
******************************************************************************
*
-* Copyright (C) 1997-2011, International Business Machines
+* Copyright (C) 1997-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
// For example:
//
-// UMTX myMutex;
+// UMutex myMutex;
//
// void Function(int arg1, int arg2)
// {
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);
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;
/**
*******************************************************************************
-* Copyright (C) 2001-2011, International Business Machines Corporation.
+* Copyright (C) 2001-2012, International Business Machines Corporation.
* All Rights Reserved.
*******************************************************************************
*/
******************************************************************
*/
-static UMTX lock;
+static UMutex lock = U_MUTEX_INITIALIZER;
ICUService::ICUService()
: name()
// 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)
{
}
private:
- UMTX *fMutex;
+ UMutex *fMutex;
UBool fActive;
};
/**
*******************************************************************************
- * Copyright (C) 2001-2011, International Business Machines Corporation and *
+ * Copyright (C) 2001-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
U_NAMESPACE_BEGIN
-static UMTX llock;
+static UMutex llock = U_MUTEX_INITIALIZER;
ICULocaleService::ICULocaleService()
: fallbackLocale(Locale::getDefault())
{
/**
*******************************************************************************
- * Copyright (C) 2001-2011, International Business Machines Corporation and *
+ * Copyright (C) 2001-2012, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
EventListener::~EventListener() {}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener)
-static UMTX notifyLock;
+static UMutex notifyLock = U_MUTEX_INITIALIZER;
ICUNotifier::ICUNotifier(void)
: listeners(NULL)
/*
*******************************************************************************
*
-* Copyright (C) 2004-2011, International Business Machines
+* Copyright (C) 2004-2012, International Business Machines
* Corporation and others. All Rights Reserved.
*
*******************************************************************************
#include "unicode/udata.h" /* UDataInfo */
#include "ucmndata.h" /* DataHeader */
#include "udatamem.h"
-#include "umutex.h"
#include "uassert.h"
#include "cmemory.h"
#include "utrie2.h"
#include "unicode/uscript.h"
#include "unicode/udata.h"
#include "uassert.h"
-#include "umutex.h"
#include "cmemory.h"
#include "ucln_cmn.h"
#include "utrie2.h"
#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
#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];
ucln_lib_cleanup();
- umtx_destroy(&gICUInitMutex);
umtx_cleanup();
cmemory_cleanup(); /* undo any heap functions set by u_setMemoryFunctions(). */
gICUInitialized = FALSE;
/*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;
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);
}
#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
* 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) {
#include "icuplugimp.h"
#include "ucln.h"
#include "ucnv_io.h"
-#include "umutex.h"
#include "utracimp.h"
static void U_CALLCONV
+++ /dev/null
-/*
-******************************************************************************
-*
-* 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;
-}
-
-
--- /dev/null
+/*
+******************************************************************************
+*
+* 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;
+}
#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.
*/
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) {
cache = NULL;
}
}
- if (cache == NULL && resbMutex != NULL) {
- umtx_destroy(&resbMutex);
- }
return (cache == NULL);
}
*/
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 };
}
}
- 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
// 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)) {
/************************************************************************
- * 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
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
/*
******************************************************************************
- * Copyright (C) 2007-2011, International Business Machines Corporation
+ * Copyright (C) 2007-2012, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
// --- 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;
delete gChineseCalendarNewYearCache;
gChineseCalendarNewYearCache = NULL;
}
- umtx_destroy(&astroLock);
return TRUE;
}
U_CDECL_END
UHashtable *cache;
};
-static UMTX lock;
+static UMutex lock = U_MUTEX_INITIALIZER;
U_CDECL_BEGIN
static void U_CALLCONV
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.
#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";
U_CDECL_BEGIN
static UBool U_CALLCONV gender_cleanup(void) {
- umtx_destroy(&gGenderMetaLock);
if (gGenderInfoCache != NULL) {
uhash_close(gGenderInfoCache);
gGenderInfoCache = NULL;
/*
******************************************************************************
-* Copyright (C) 2003-2011, International Business Machines Corporation
+* Copyright (C) 2003-2012, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
// --- 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;
delete gIslamicCalendarAstro;
gIslamicCalendarAstro = NULL;
}
- umtx_destroy(&astroLock);
return TRUE;
}
U_CDECL_END
// 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;
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])
/*
**********************************************************************
-* Copyright (C) 1999-2008, International Business Machines
+* Copyright (C) 1999-2012, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Date Name Description
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,
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)
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;
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
/**
* The mutex controlling access to registry object.
*/
-static UMTX registryMutex = 0;
+static UMutex registryMutex = U_MUTEX_INITIALIZER;
/**
* System transliterator registry; non-null when initialized.
delete registry;
registry = NULL;
}
- umtx_destroy(®istryMutex);
return TRUE;
}
/*
**********************************************************************
-* Copyright (c) 2002-2011, International Business Machines Corporation
+* Copyright (c) 2002-2012, International Business Machines Corporation
* and others. All Rights Reserved.
**********************************************************************
* Date Name Description
/**
* 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,
delete SPECIAL_INVERSES;
SPECIAL_INVERSES = NULL;
}
- umtx_destroy(&LOCK);
}
U_NAMESPACE_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;
for (int32_t i = 0; i <= UTZFMT_PAT_NEGATIVE_HMS; i++) {
delete fGMTOffsetPatternItems[i];
}
- umtx_destroy(&fLock);
}
TimeZoneFormat&
return name;
}
+static UMutex gLock = U_MUTEX_INITIALIZER;
+
const TimeZoneGenericNames*
TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
if (U_FAILURE(status)) {
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;
return results;
}
+static UMutex gLock = U_MUTEX_INITIALIZER;
+
class TZGNCore : public UMemory {
public:
TZGNCore(const Locale& locale, UErrorCode& status);
private:
Locale fLocale;
- UMTX fLock;
const TimeZoneNames* fTimeZoneNames;
UHashtable* fLocationNamesMap;
UHashtable* fPartialLocationNamesMap;
// ---------------------------------------------------
TZGNCore::TZGNCore(const Locale& locale, UErrorCode& status)
: fLocale(locale),
- fLock(NULL),
fTimeZoneNames(NULL),
fLocationNamesMap(NULL),
fPartialLocationNamesMap(NULL),
TZGNCore::~TZGNCore() {
cleanup();
- umtx_destroy(&fLock);
}
void
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();
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();
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;
// 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);
}
}
}
- 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) {
} TZGNCoreRef;
// TZGNCore object cache handling
-static UMTX gTZGNLock = NULL;
+static UMutex gTZGNLock = U_MUTEX_INITIALIZER;
static UHashtable *gTZGNCoreCache = NULL;
static UBool gTZGNCoreCacheInitialized = FALSE;
*/
static UBool U_CALLCONV tzgnCore_cleanup(void)
{
- umtx_destroy(&gTZGNLock);
-
if (gTZGNCoreCache != NULL) {
uhash_close(gTZGNCoreCache);
gTZGNCoreCache = NULL;
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;
*/
static UBool U_CALLCONV timeZoneNames_cleanup(void)
{
- umtx_destroy(&gTimeZoneNamesLock);
-
if (gTimeZoneNamesCache != NULL) {
uhash_close(gTimeZoneNamesCache);
gTimeZoneNamesCache = NULL;
}
// 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
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),
TimeZoneNamesImpl::~TimeZoneNamesImpl() {
cleanup();
- umtx_destroy(&fLock);
}
void
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);
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);
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();
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;
delete matches;
// All names are not yet loaded into the trie
- umtx_lock(&nonConstThis->fLock);
+ umtx_lock(&gLock);
{
if (!fNamesTrieFullyLoaded) {
const UnicodeString *id;
}
}
}
- 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);
}
private:
Locale fLocale;
- UMTX fLock;
UResourceBundle* fZoneStrings;
static UHashtable* gIsoCodes = NULL;
static UBool gIsoCodesInitialized = FALSE;
-static UMTX gIsoCodesLock = NULL;
+static UMutex gIsoCodesLock = U_MUTEX_INITIALIZER;
//------------------------------------------------------------
// Code
static UBool U_CALLCONV
isoCodes_cleanup(void)
{
- if (gIsoCodesLock != NULL) {
- umtx_destroy(&gIsoCodesLock);
- }
-
if (gIsoCodes != NULL) {
uhash_close(gIsoCodes);
gIsoCodes = NULL;
#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 {
gCRegHead = gCRegHead->next;
delete n;
}
- umtx_destroy(&gCRegLock);
}
};
U_CDECL_END
-typedef void *UMTX;
-
U_NAMESPACE_BEGIN
class TimeZoneGenericNames;
TimeZoneFormat(const Locale& locale, UErrorCode& status);
private:
- /* mutex */
- UMTX fLock;
-
/* Locale of this object */
Locale fLocale;
#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;
*/
static UBool U_CALLCONV zoneMeta_cleanup(void)
{
- umtx_destroy(&gZoneMetaLock);
-
if (gCanonicalIDCache != NULL) {
uhash_close(gCanonicalIDCache);
gCanonicalIDCache = NULL;
// 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;
}
// 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];