From bc4bb89af274f17ef28ec7bccd4c25c696120d6a Mon Sep 17 00:00:00 2001 From: Andy Heninger Date: Mon, 11 Mar 2019 16:36:33 -0700 Subject: [PATCH] ICU-20488 mutex static constructor fixes. Remove the dependencies from the ICU library code on static constructors that were introduced by using std::mutex and condition variables. The mutexes are lazily initialized by embedding them as local static variables in getter functions, and relying on the C++ compiler/runtime to do thread safe initialization of them. --- icu4c/source/common/brkeng.cpp | 3 +- icu4c/source/common/characterproperties.cpp | 9 ++- icu4c/source/common/locdspnm.cpp | 4 +- icu4c/source/common/locid.cpp | 9 ++- icu4c/source/common/putil.cpp | 2 +- icu4c/source/common/resbund.cpp | 2 +- icu4c/source/common/serv.cpp | 21 +++--- icu4c/source/common/servls.cpp | 2 +- icu4c/source/common/servnotf.cpp | 13 ++-- icu4c/source/common/ucnv_bld.cpp | 31 +++++---- icu4c/source/common/ucurr.cpp | 34 +++++---- icu4c/source/common/umutex.cpp | 30 +++++--- icu4c/source/common/unifiedcache.cpp | 34 +++++---- icu4c/source/common/uresbund.cpp | 33 +++++---- icu4c/source/common/usprep.cpp | 27 ++++---- icu4c/source/i18n/astro.cpp | 17 +++-- icu4c/source/i18n/chnsecal.cpp | 17 +++-- icu4c/source/i18n/dtfmtsym.cpp | 3 +- icu4c/source/i18n/dtitvfmt.cpp | 19 +++--- icu4c/source/i18n/gender.cpp | 3 +- icu4c/source/i18n/islamcal.cpp | 2 +- icu4c/source/i18n/listformatter.cpp | 2 +- icu4c/source/i18n/numfmt.cpp | 2 +- icu4c/source/i18n/rbt.cpp | 3 +- icu4c/source/i18n/rbtz.cpp | 2 +- icu4c/source/i18n/reldatefmt.cpp | 3 +- icu4c/source/i18n/simpletz.cpp | 2 +- icu4c/source/i18n/smpdtfmt.cpp | 13 ++-- icu4c/source/i18n/translit.cpp | 43 ++++++------ icu4c/source/i18n/tridpars.cpp | 11 +-- icu4c/source/i18n/tzfmt.cpp | 13 ++-- icu4c/source/i18n/tzgnames.cpp | 40 ++++++----- icu4c/source/i18n/tznames.cpp | 15 ++-- icu4c/source/i18n/tznames_impl.cpp | 27 +++++--- icu4c/source/i18n/zonemeta.cpp | 29 ++++---- icu4c/source/io/locbund.cpp | 2 +- icu4c/source/test/intltest/intltest.cpp | 2 +- icu4c/source/test/intltest/tsmthred.cpp | 76 ++++++++++++--------- 38 files changed, 345 insertions(+), 255 deletions(-) diff --git a/icu4c/source/common/brkeng.cpp b/icu4c/source/common/brkeng.cpp index 7144af60b24..19467dc2526 100644 --- a/icu4c/source/common/brkeng.cpp +++ b/icu4c/source/common/brkeng.cpp @@ -124,13 +124,12 @@ static void U_CALLCONV _deleteEngine(void *obj) { U_CDECL_END U_NAMESPACE_BEGIN -static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER; - const LanguageBreakEngine * ICULanguageBreakFactory::getEngineFor(UChar32 c) { const LanguageBreakEngine *lbe = NULL; UErrorCode status = U_ZERO_ERROR; + static UMutex gBreakEngineMutex = U_MUTEX_INITIALIZER; Mutex m(&gBreakEngineMutex); if (fEngines == NULL) { diff --git a/icu4c/source/common/characterproperties.cpp b/icu4c/source/common/characterproperties.cpp index 96186e64181..5a57364375b 100644 --- a/icu4c/source/common/characterproperties.cpp +++ b/icu4c/source/common/characterproperties.cpp @@ -47,7 +47,10 @@ UnicodeSet *sets[UCHAR_BINARY_LIMIT] = {}; UCPMap *maps[UCHAR_INT_LIMIT - UCHAR_INT_START] = {}; -icu::UMutex cpMutex = U_MUTEX_INITIALIZER; +icu::UMutex *cpMutex() { + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} //---------------------------------------------------------------- // Inclusions list @@ -358,7 +361,7 @@ u_getBinaryPropertySet(UProperty property, UErrorCode *pErrorCode) { *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - Mutex m(&cpMutex); + Mutex m(cpMutex()); UnicodeSet *set = sets[property]; if (set == nullptr) { sets[property] = set = makeSet(property, *pErrorCode); @@ -374,7 +377,7 @@ u_getIntPropertyMap(UProperty property, UErrorCode *pErrorCode) { *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; return nullptr; } - Mutex m(&cpMutex); + Mutex m(cpMutex()); UCPMap *map = maps[property - UCHAR_INT_START]; if (map == nullptr) { maps[property - UCHAR_INT_START] = map = makeMap(property, *pErrorCode); diff --git a/icu4c/source/common/locdspnm.cpp b/icu4c/source/common/locdspnm.cpp index 2d9389e910a..da35be9e766 100644 --- a/icu4c/source/common/locdspnm.cpp +++ b/icu4c/source/common/locdspnm.cpp @@ -286,7 +286,6 @@ class LocaleDisplayNamesImpl : public LocaleDisplayNames { #else UObject* capitalizationBrkIter; #endif - static UMutex capitalizationBrkIterLock; UnicodeString formatOpenParen; UnicodeString formatReplaceOpenParen; UnicodeString formatCloseParen; @@ -352,8 +351,6 @@ private: struct CapitalizationContextSink; }; -UMutex LocaleDisplayNamesImpl::capitalizationBrkIterLock = U_MUTEX_INITIALIZER; - LocaleDisplayNamesImpl::LocaleDisplayNamesImpl(const Locale& locale, UDialectHandling dialectHandling) : dialectHandling(dialectHandling) @@ -552,6 +549,7 @@ LocaleDisplayNamesImpl::adjustForUsageAndContext(CapContextUsage usage, if ( result.length() > 0 && u_islower(result.char32At(0)) && capitalizationBrkIter!= NULL && ( capitalizationContext==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE || fCapitalization[usage] ) ) { // note fCapitalization[usage] won't be set unless capitalizationContext is UI_LIST_OR_MENU or STANDALONE + static UMutex capitalizationBrkIterLock = U_MUTEX_INITIALIZER; Mutex lock(&capitalizationBrkIterLock); result.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT); } diff --git a/icu4c/source/common/locid.cpp b/icu4c/source/common/locid.cpp index a6a518201c2..06986b636ad 100644 --- a/icu4c/source/common/locid.cpp +++ b/icu4c/source/common/locid.cpp @@ -62,7 +62,10 @@ static Locale *gLocaleCache = NULL; static UInitOnce gLocaleCacheInitOnce = U_INITONCE_INITIALIZER; // gDefaultLocaleMutex protects all access to gDefaultLocalesHashT and gDefaultLocale. -static UMutex gDefaultLocaleMutex = U_MUTEX_INITIALIZER; +static UMutex *gDefaultLocaleMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} static UHashtable *gDefaultLocalesHashT = NULL; static Locale *gDefaultLocale = NULL; @@ -171,7 +174,7 @@ U_NAMESPACE_BEGIN Locale *locale_set_default_internal(const char *id, UErrorCode& status) { // Synchronize this entire function. - Mutex lock(&gDefaultLocaleMutex); + Mutex lock(gDefaultLocaleMutex()); UBool canonicalize = FALSE; @@ -708,7 +711,7 @@ const Locale& U_EXPORT2 Locale::getDefault() { { - Mutex lock(&gDefaultLocaleMutex); + Mutex lock(gDefaultLocaleMutex()); if (gDefaultLocale != NULL) { return *gDefaultLocale; } diff --git a/icu4c/source/common/putil.cpp b/icu4c/source/common/putil.cpp index 9ed85c00a05..42db744c774 100644 --- a/icu4c/source/common/putil.cpp +++ b/icu4c/source/common/putil.cpp @@ -241,7 +241,6 @@ 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 UMutex fakeClockMutex = U_MUTEX_INTIALIZER; static UDate getUTCtime_real() { struct timeval posixTime; @@ -250,6 +249,7 @@ static UDate getUTCtime_real() { } static UDate getUTCtime_fake() { + static UMutex fakeClockMutex = U_MUTEX_INTIALIZER; umtx_lock(&fakeClockMutex); if(!fakeClock_set) { UDate real = getUTCtime_real(); diff --git a/icu4c/source/common/resbund.cpp b/icu4c/source/common/resbund.cpp index 512bd531f23..08cda3a97b5 100644 --- a/icu4c/source/common/resbund.cpp +++ b/icu4c/source/common/resbund.cpp @@ -376,8 +376,8 @@ void ResourceBundle::getVersion(UVersionInfo versionInfo) const { ures_getVersion(fResource, versionInfo); } -static UMutex gLocaleLock = U_MUTEX_INITIALIZER; const Locale &ResourceBundle::getLocale(void) const { + static UMutex gLocaleLock = U_MUTEX_INITIALIZER; Mutex lock(&gLocaleLock); if (fLocale != NULL) { return *fLocale; diff --git a/icu4c/source/common/serv.cpp b/icu4c/source/common/serv.cpp index 619e8c7c8bd..555c0555dfb 100644 --- a/icu4c/source/common/serv.cpp +++ b/icu4c/source/common/serv.cpp @@ -333,7 +333,10 @@ U_CDECL_END ****************************************************************** */ -static UMutex lock = U_MUTEX_INITIALIZER; +static UMutex *lock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} ICUService::ICUService() : name() @@ -358,7 +361,7 @@ ICUService::ICUService(const UnicodeString& newName) ICUService::~ICUService() { { - Mutex mutex(&lock); + Mutex mutex(lock()); clearCaches(); delete factories; factories = NULL; @@ -449,7 +452,7 @@ ICUService::getKey(ICUServiceKey& key, UnicodeString* actualReturn, const ICUSer // if factory is not null, we're calling from within the mutex, // and since some unix machines don't have reentrant mutexes we // need to make sure not to try to lock it again. - XMutex mutex(&lock, factory != NULL); + XMutex mutex(lock(), factory != NULL); if (serviceCache == NULL) { ncthis->serviceCache = new Hashtable(status); @@ -615,7 +618,7 @@ ICUService::getVisibleIDs(UVector& result, const UnicodeString* matchID, UErrorC } { - Mutex mutex(&lock); + Mutex mutex(lock()); const Hashtable* map = getVisibleIDMap(status); if (map != NULL) { ICUServiceKey* fallbackKey = createKey(matchID, status); @@ -692,7 +695,7 @@ ICUService::getDisplayName(const UnicodeString& id, UnicodeString& result, const { { UErrorCode status = U_ZERO_ERROR; - Mutex mutex(&lock); + Mutex mutex(lock()); const Hashtable* map = getVisibleIDMap(status); if (map != NULL) { ICUServiceFactory* f = (ICUServiceFactory*)map->get(id); @@ -744,7 +747,7 @@ ICUService::getDisplayNames(UVector& result, result.setDeleter(userv_deleteStringPair); if (U_SUCCESS(status)) { ICUService* ncthis = (ICUService*)this; // cast away semantic const - Mutex mutex(&lock); + Mutex mutex(lock()); if (dnCache != NULL && dnCache->locale != locale) { delete dnCache; @@ -849,7 +852,7 @@ URegistryKey ICUService::registerFactory(ICUServiceFactory* factoryToAdopt, UErrorCode& status) { if (U_SUCCESS(status) && factoryToAdopt != NULL) { - Mutex mutex(&lock); + Mutex mutex(lock()); if (factories == NULL) { factories = new UVector(deleteUObject, NULL, status); @@ -880,7 +883,7 @@ ICUService::unregister(URegistryKey rkey, UErrorCode& status) ICUServiceFactory *factory = (ICUServiceFactory*)rkey; UBool result = FALSE; if (factory != NULL && factories != NULL) { - Mutex mutex(&lock); + Mutex mutex(lock()); if (factories->removeElement(factory)) { clearCaches(); @@ -900,7 +903,7 @@ void ICUService::reset() { { - Mutex mutex(&lock); + Mutex mutex(lock()); reInitializeFactories(); clearCaches(); } diff --git a/icu4c/source/common/servls.cpp b/icu4c/source/common/servls.cpp index f4579d0eecd..90874d11c14 100644 --- a/icu4c/source/common/servls.cpp +++ b/icu4c/source/common/servls.cpp @@ -26,7 +26,6 @@ U_NAMESPACE_BEGIN -static UMutex llock = U_MUTEX_INITIALIZER; ICULocaleService::ICULocaleService() : fallbackLocale(Locale::getDefault()) { @@ -264,6 +263,7 @@ ICULocaleService::validateFallbackLocale() const { const Locale& loc = Locale::getDefault(); ICULocaleService* ncThis = (ICULocaleService*)this; + static UMutex llock = U_MUTEX_INITIALIZER; { Mutex mutex(&llock); if (loc != fallbackLocale) { diff --git a/icu4c/source/common/servnotf.cpp b/icu4c/source/common/servnotf.cpp index dc77c7b857d..1e65a147d85 100644 --- a/icu4c/source/common/servnotf.cpp +++ b/icu4c/source/common/servnotf.cpp @@ -21,7 +21,10 @@ U_NAMESPACE_BEGIN EventListener::~EventListener() {} UOBJECT_DEFINE_RTTI_IMPLEMENTATION(EventListener) -static UMutex notifyLock = U_MUTEX_INITIALIZER; +static UMutex *notifyLock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} ICUNotifier::ICUNotifier(void) : listeners(NULL) @@ -30,7 +33,7 @@ ICUNotifier::ICUNotifier(void) ICUNotifier::~ICUNotifier(void) { { - Mutex lmx(¬ifyLock); + Mutex lmx(notifyLock()); delete listeners; listeners = NULL; } @@ -47,7 +50,7 @@ ICUNotifier::addListener(const EventListener* l, UErrorCode& status) } if (acceptsListener(*l)) { - Mutex lmx(¬ifyLock); + Mutex lmx(notifyLock()); if (listeners == NULL) { listeners = new UVector(5, status); } else { @@ -80,7 +83,7 @@ ICUNotifier::removeListener(const EventListener *l, UErrorCode& status) } { - Mutex lmx(¬ifyLock); + Mutex lmx(notifyLock()); if (listeners != NULL) { // identity equality check for (int i = 0, e = listeners->size(); i < e; ++i) { @@ -103,7 +106,7 @@ void ICUNotifier::notifyChanged(void) { if (listeners != NULL) { - Mutex lmx(¬ifyLock); + Mutex lmx(notifyLock()); if (listeners != NULL) { for (int i = 0, e = listeners->size(); i < e; ++i) { EventListener* el = (EventListener*)listeners->elementAt(i); diff --git a/icu4c/source/common/ucnv_bld.cpp b/icu4c/source/common/ucnv_bld.cpp index 18e46e16955..b71be8fdad3 100644 --- a/icu4c/source/common/ucnv_bld.cpp +++ b/icu4c/source/common/ucnv_bld.cpp @@ -194,9 +194,12 @@ static struct { /*initializes some global variables */ static UHashtable *SHARED_DATA_HASHTABLE = NULL; -static icu::UMutex cnvCacheMutex = U_MUTEX_INITIALIZER; /* Mutex for synchronizing cnv cache access. */ - /* Note: the global mutex is used for */ - /* reference count updates. */ +static icu::UMutex *cnvCacheMutex() { /* Mutex for synchronizing cnv cache access. */ + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} +/* Note: the global mutex is used for */ +/* reference count updates. */ static const char **gAvailableConverters = NULL; static uint16_t gAvailableConverterCount = 0; @@ -599,9 +602,9 @@ U_CFUNC void ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData) { if(sharedData != NULL && sharedData->isReferenceCounted) { - umtx_lock(&cnvCacheMutex); + umtx_lock(cnvCacheMutex()); ucnv_unload(sharedData); - umtx_unlock(&cnvCacheMutex); + umtx_unlock(cnvCacheMutex()); } } @@ -609,9 +612,9 @@ U_CFUNC void ucnv_incrementRefCount(UConverterSharedData *sharedData) { if(sharedData != NULL && sharedData->isReferenceCounted) { - umtx_lock(&cnvCacheMutex); + umtx_lock(cnvCacheMutex()); sharedData->referenceCounter++; - umtx_unlock(&cnvCacheMutex); + umtx_unlock(cnvCacheMutex()); } } @@ -812,9 +815,9 @@ ucnv_loadSharedData(const char *converterName, pArgs->nestedLoads=1; pArgs->pkg=NULL; - umtx_lock(&cnvCacheMutex); + umtx_lock(cnvCacheMutex()); mySharedConverterData = ucnv_load(pArgs, err); - umtx_unlock(&cnvCacheMutex); + umtx_unlock(cnvCacheMutex()); if (U_FAILURE (*err) || (mySharedConverterData == NULL)) { return NULL; @@ -1061,7 +1064,7 @@ ucnv_flushCache () * because the sequence of looking up in the cache + incrementing * is protected by cnvCacheMutex. */ - umtx_lock(&cnvCacheMutex); + umtx_lock(cnvCacheMutex()); /* * double loop: A delta/extension-only converter has a pointer to its base table's * shared data; the first iteration of the outer loop may see the delta converter @@ -1090,7 +1093,7 @@ ucnv_flushCache () } } } while(++i == 1 && remaining > 0); - umtx_unlock(&cnvCacheMutex); + umtx_unlock(cnvCacheMutex()); UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining); @@ -1196,7 +1199,7 @@ internalSetName(const char *name, UErrorCode *status) { } algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name); - umtx_lock(&cnvCacheMutex); + umtx_lock(cnvCacheMutex()); gDefaultAlgorithmicSharedData = algorithmicSharedData; gDefaultConverterContainsOption = containsOption; @@ -1212,7 +1215,7 @@ internalSetName(const char *name, UErrorCode *status) { ucnv_enableCleanup(); - umtx_unlock(&cnvCacheMutex); + umtx_unlock(cnvCacheMutex()); } #endif @@ -1237,7 +1240,7 @@ ucnv_getDefaultName() { but ucnv_setDefaultName is not thread safe. */ { - icu::Mutex lock(&cnvCacheMutex); + icu::Mutex lock(cnvCacheMutex()); name = gDefaultConverterName; } if(name==NULL) { diff --git a/icu4c/source/common/ucurr.cpp b/icu4c/source/common/ucurr.cpp index 802eafba166..444adc09e09 100644 --- a/icu4c/source/common/ucurr.cpp +++ b/icu4c/source/common/ucurr.cpp @@ -365,7 +365,10 @@ U_CDECL_END #if !UCONFIG_NO_SERVICE struct CReg; -static UMutex gCRegLock = U_MUTEX_INITIALIZER; +static UMutex *gCRegLock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} static CReg* gCRegHead = 0; struct CReg : public icu::UMemory { @@ -391,14 +394,14 @@ struct CReg : public icu::UMemory { if (status && U_SUCCESS(*status) && _iso && _id) { CReg* n = new CReg(_iso, _id); if (n) { - umtx_lock(&gCRegLock); + umtx_lock(gCRegLock()); if (!gCRegHead) { /* register for the first time */ ucln_common_registerCleanup(UCLN_COMMON_CURRENCY, currency_cleanup); } n->next = gCRegHead; gCRegHead = n; - umtx_unlock(&gCRegLock); + umtx_unlock(gCRegLock()); return n; } *status = U_MEMORY_ALLOCATION_ERROR; @@ -408,7 +411,7 @@ struct CReg : public icu::UMemory { static UBool unreg(UCurrRegistryKey key) { UBool found = FALSE; - umtx_lock(&gCRegLock); + umtx_lock(gCRegLock()); CReg** p = &gCRegHead; while (*p) { @@ -421,13 +424,13 @@ struct CReg : public icu::UMemory { p = &((*p)->next); } - umtx_unlock(&gCRegLock); + umtx_unlock(gCRegLock()); return found; } static const UChar* get(const char* id) { const UChar* result = NULL; - umtx_lock(&gCRegLock); + umtx_lock(gCRegLock()); CReg* p = gCRegHead; /* register cleanup of the mutex */ @@ -439,7 +442,7 @@ struct CReg : public icu::UMemory { } p = p->next; } - umtx_unlock(&gCRegLock); + umtx_unlock(gCRegLock()); return result; } @@ -1353,7 +1356,10 @@ static CurrencyNameCacheEntry* currCache[CURRENCY_NAME_CACHE_NUM] = {NULL}; // It is a simple round-robin replacement strategy. static int8_t currentCacheEntryIndex = 0; -static UMutex gCurrencyCacheMutex = U_MUTEX_INITIALIZER; +static UMutex *gCurrencyCacheMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} // Cache deletion static void @@ -1402,7 +1408,7 @@ getCacheEntry(const char* locale, UErrorCode& ec) { CurrencyNameStruct* currencySymbols = NULL; CurrencyNameCacheEntry* cacheEntry = NULL; - umtx_lock(&gCurrencyCacheMutex); + umtx_lock(gCurrencyCacheMutex()); // in order to handle racing correctly, // not putting 'search' in a separate function. int8_t found = -1; @@ -1417,13 +1423,13 @@ getCacheEntry(const char* locale, UErrorCode& ec) { cacheEntry = currCache[found]; ++(cacheEntry->refCount); } - umtx_unlock(&gCurrencyCacheMutex); + umtx_unlock(gCurrencyCacheMutex()); if (found == -1) { collectCurrencyNames(locale, ¤cyNames, &total_currency_name_count, ¤cySymbols, &total_currency_symbol_count, ec); if (U_FAILURE(ec)) { return NULL; } - umtx_lock(&gCurrencyCacheMutex); + umtx_lock(gCurrencyCacheMutex()); // check again. for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) { if (currCache[i]!= NULL && @@ -1462,19 +1468,19 @@ getCacheEntry(const char* locale, UErrorCode& ec) { cacheEntry = currCache[found]; ++(cacheEntry->refCount); } - umtx_unlock(&gCurrencyCacheMutex); + umtx_unlock(gCurrencyCacheMutex()); } return cacheEntry; } static void releaseCacheEntry(CurrencyNameCacheEntry* cacheEntry) { - umtx_lock(&gCurrencyCacheMutex); + umtx_lock(gCurrencyCacheMutex()); --(cacheEntry->refCount); if (cacheEntry->refCount == 0) { // remove deleteCacheEntry(cacheEntry); } - umtx_unlock(&gCurrencyCacheMutex); + umtx_unlock(gCurrencyCacheMutex()); } U_CAPI void diff --git a/icu4c/source/common/umutex.cpp b/icu4c/source/common/umutex.cpp index 7873314f1a4..20b03d6cd3e 100644 --- a/icu4c/source/common/umutex.cpp +++ b/icu4c/source/common/umutex.cpp @@ -42,12 +42,15 @@ U_NAMESPACE_BEGIN *************************************************************************************************/ // The ICU global mutex. Used when ICU implementation code passes NULL for the mutex pointer. -static UMutex globalMutex = U_MUTEX_INITIALIZER; +static UMutex *globalMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} U_CAPI void U_EXPORT2 umtx_lock(UMutex *mutex) { if (mutex == nullptr) { - mutex = &globalMutex; + mutex = globalMutex(); } mutex->fMutex.lock(); } @@ -57,7 +60,7 @@ U_CAPI void U_EXPORT2 umtx_unlock(UMutex* mutex) { if (mutex == nullptr) { - mutex = &globalMutex; + mutex = globalMutex(); } mutex->fMutex.unlock(); } @@ -71,7 +74,7 @@ UConditionVar::~UConditionVar() { U_CAPI void U_EXPORT2 umtx_condWait(UConditionVar *cond, UMutex *mutex) { if (mutex == nullptr) { - mutex = &globalMutex; + mutex = globalMutex(); } cond->fCV.wait(mutex->fMutex); } @@ -95,8 +98,15 @@ umtx_condSignal(UConditionVar *cond) { * *************************************************************************************************/ -static std::mutex initMutex; -static std::condition_variable initCondition; +static std::mutex &initMutex() { + static std::mutex m; + return m; +} + +static std::condition_variable &initCondition() { + static std::condition_variable cv; + return cv; +} // This function is called when a test of a UInitOnce::fState reveals that @@ -109,7 +119,7 @@ static std::condition_variable initCondition; // U_COMMON_API UBool U_EXPORT2 umtx_initImplPreInit(UInitOnce &uio) { - std::unique_lock lock(initMutex); + std::unique_lock lock(initMutex()); if (umtx_loadAcquire(uio.fState) == 0) { umtx_storeRelease(uio.fState, 1); @@ -118,7 +128,7 @@ umtx_initImplPreInit(UInitOnce &uio) { while (umtx_loadAcquire(uio.fState) == 1) { // Another thread is currently running the initialization. // Wait until it completes. - initCondition.wait(lock); + initCondition().wait(lock); } U_ASSERT(uio.fState == 2); return false; @@ -135,10 +145,10 @@ umtx_initImplPreInit(UInitOnce &uio) { U_COMMON_API void U_EXPORT2 umtx_initImplPostInit(UInitOnce &uio) { { - std::unique_lock lock(initMutex); + std::unique_lock lock(initMutex()); umtx_storeRelease(uio.fState, 2); } - initCondition.notify_all(); + initCondition().notify_all(); } U_NAMESPACE_END diff --git a/icu4c/source/common/unifiedcache.cpp b/icu4c/source/common/unifiedcache.cpp index 6ad8c3d1c7b..641f4ec6594 100644 --- a/icu4c/source/common/unifiedcache.cpp +++ b/icu4c/source/common/unifiedcache.cpp @@ -21,8 +21,14 @@ #include "umutex.h" static icu::UnifiedCache *gCache = NULL; -static icu::UMutex gCacheMutex = U_MUTEX_INITIALIZER; -static icu::UConditionVar gInProgressValueAddedCond = U_CONDITION_INITIALIZER; +static icu::UMutex *gCacheMutex() { + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} +static icu::UConditionVar *gInProgressValueAddedCond() { + static icu::UConditionVar cv = U_CONDITION_INITIALIZER; + return &cv; +} static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; static const int32_t MAX_EVICT_ITERATIONS = 10; @@ -132,28 +138,28 @@ void UnifiedCache::setEvictionPolicy( status = U_ILLEGAL_ARGUMENT_ERROR; return; } - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); fMaxUnused = count; fMaxPercentageOfInUse = percentageOfInUseItems; } int32_t UnifiedCache::unusedCount() const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); return uhash_count(fHashtable) - fNumValuesInUse; } int64_t UnifiedCache::autoEvictedCount() const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); return fAutoEvictedCount; } int32_t UnifiedCache::keyCount() const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); return uhash_count(fHashtable); } void UnifiedCache::flush() const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); // Use a loop in case cache items that are flushed held hard references to // other cache items making those additional cache items eligible for @@ -162,7 +168,7 @@ void UnifiedCache::flush() const { } void UnifiedCache::handleUnreferencedObject() const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); --fNumValuesInUse; _runEvictionSlice(); } @@ -181,7 +187,7 @@ void UnifiedCache::dump() { } void UnifiedCache::dumpContents() const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); _dumpContents(); } @@ -221,7 +227,7 @@ UnifiedCache::~UnifiedCache() { // Now all that should be left in the cache are entries that refer to // each other and entries with hard references from outside the cache. // Nothing we can do about these so proceed to wipe out the cache. - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); _flush(TRUE); } uhash_close(fHashtable); @@ -322,7 +328,7 @@ void UnifiedCache::_putIfAbsentAndGet( const CacheKeyBase &key, const SharedObject *&value, UErrorCode &status) const { - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); const UHashElement *element = uhash_find(fHashtable, &key); if (element != NULL && !_inProgress(element)) { _fetch(element, value, status); @@ -347,14 +353,14 @@ UBool UnifiedCache::_poll( UErrorCode &status) const { U_ASSERT(value == NULL); U_ASSERT(status == U_ZERO_ERROR); - Mutex lock(&gCacheMutex); + Mutex lock(gCacheMutex()); const UHashElement *element = uhash_find(fHashtable, &key); // If the hash table contains an inProgress placeholder entry for this key, // this means that another thread is currently constructing the value object. // Loop, waiting for that construction to complete. while (element != NULL && _inProgress(element)) { - umtx_condWait(&gInProgressValueAddedCond, &gCacheMutex); + umtx_condWait(gInProgressValueAddedCond(), gCacheMutex()); element = uhash_find(fHashtable, &key); } @@ -427,7 +433,7 @@ void UnifiedCache::_put( // Tell waiting threads that we replace in-progress status with // an error. - umtx_condBroadcast(&gInProgressValueAddedCond); + umtx_condBroadcast(gInProgressValueAddedCond()); } void UnifiedCache::_fetch( diff --git a/icu4c/source/common/uresbund.cpp b/icu4c/source/common/uresbund.cpp index 45bb92b804d..af6d1a1f7c1 100644 --- a/icu4c/source/common/uresbund.cpp +++ b/icu4c/source/common/uresbund.cpp @@ -49,7 +49,10 @@ TODO: This cache should probably be removed when the deprecated code is static UHashtable *cache = NULL; static icu::UInitOnce gCacheInitOnce; -static UMutex resbMutex = U_MUTEX_INITIALIZER; +static UMutex *resbMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} /* INTERNAL: hashes an entry */ static int32_t U_CALLCONV hashEntry(const UHashTok parm) { @@ -93,13 +96,13 @@ static UBool chopLocale(char *name) { * Internal function */ static void entryIncrease(UResourceDataEntry *entry) { - umtx_lock(&resbMutex); + umtx_lock(resbMutex()); entry->fCountExisting++; while(entry->fParent != NULL) { entry = entry->fParent; entry->fCountExisting++; } - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); } /** @@ -181,9 +184,9 @@ static int32_t ures_flushCache() /*if shared data hasn't even been lazy evaluated yet * return 0 */ - umtx_lock(&resbMutex); + umtx_lock(resbMutex()); if (cache == NULL) { - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); return 0; } @@ -215,7 +218,7 @@ static int32_t ures_flushCache() * got decremented by free_entry(). */ } while(deletedMore); - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); return rbDeletedNum; } @@ -229,9 +232,9 @@ U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) { const UHashElement *e; UResourceDataEntry *resB; - umtx_lock(&resbMutex); + umtx_lock(resbMutex()); if (cache == NULL) { - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); fprintf(stderr,"%s:%d: RB Cache is NULL.\n", __FILE__, __LINE__); return FALSE; } @@ -251,7 +254,7 @@ U_CAPI UBool U_EXPORT2 ures_dumpCacheContents(void) { fprintf(stderr,"%s:%d: RB Cache still contains %d items.\n", __FILE__, __LINE__, uhash_count(cache)); - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); return cacheNotEmpty; } @@ -663,7 +666,7 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, } } - umtx_lock(&resbMutex); + umtx_lock(resbMutex()); { /* umtx_lock */ /* We're going to skip all the locales that do not have any data */ r = findFirstExisting(path, name, &isRoot, &hasChopped, &isDefault, &intStatus); @@ -762,7 +765,7 @@ static UResourceDataEntry *entryOpen(const char* path, const char* localeID, } } /* umtx_lock */ finishUnlock: - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); if(U_SUCCESS(*status)) { if(intStatus != U_ZERO_ERROR) { @@ -787,7 +790,7 @@ entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) { return NULL; } - umtx_lock(&resbMutex); + umtx_lock(resbMutex()); // findFirstExisting() without fallbacks. UResourceDataEntry *r = init_entry(localeID, path, status); if(U_SUCCESS(*status)) { @@ -825,7 +828,7 @@ entryOpenDirect(const char* path, const char* localeID, UErrorCode* status) { t1 = t1->fParent; } } - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); return r; } @@ -868,9 +871,9 @@ static void entryCloseInt(UResourceDataEntry *resB) { */ static void entryClose(UResourceDataEntry *resB) { - umtx_lock(&resbMutex); + umtx_lock(resbMutex()); entryCloseInt(resB); - umtx_unlock(&resbMutex); + umtx_unlock(resbMutex()); } /* diff --git a/icu4c/source/common/usprep.cpp b/icu4c/source/common/usprep.cpp index 01238b35f5b..a05fae1c68d 100644 --- a/icu4c/source/common/usprep.cpp +++ b/icu4c/source/common/usprep.cpp @@ -47,7 +47,10 @@ Static cache for already opened StringPrep profiles static UHashtable *SHARED_DATA_HASHTABLE = NULL; static icu::UInitOnce gSharedDataInitOnce; -static UMutex usprepMutex = U_MUTEX_INITIALIZER; +static UMutex *usprepMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} /* format version of spp file */ //static uint8_t formatVersion[4]={ 0, 0, 0, 0 }; @@ -148,9 +151,9 @@ usprep_internal_flushCache(UBool noRefCount){ * if shared data hasn't even been lazy evaluated yet * return 0 */ - umtx_lock(&usprepMutex); + umtx_lock(usprepMutex()); if (SHARED_DATA_HASHTABLE == NULL) { - umtx_unlock(&usprepMutex); + umtx_unlock(usprepMutex()); return 0; } @@ -181,7 +184,7 @@ usprep_internal_flushCache(UBool noRefCount){ } } - umtx_unlock(&usprepMutex); + umtx_unlock(usprepMutex()); return deletedNum; } @@ -259,7 +262,7 @@ loadData(UStringPrepProfile* profile, } /* in the mutex block, set the data for this process */ - umtx_lock(&usprepMutex); + umtx_lock(usprepMutex()); if(profile->sprepData==NULL) { profile->sprepData=dataMemory; dataMemory=NULL; @@ -268,7 +271,7 @@ loadData(UStringPrepProfile* profile, } else { p=(const int32_t *)udata_getMemory(profile->sprepData); } - umtx_unlock(&usprepMutex); + umtx_unlock(usprepMutex()); /* initialize some variables */ profile->mappingData=(uint16_t *)((uint8_t *)(p+_SPREP_INDEX_TOP)+profile->indexes[_SPREP_INDEX_TRIE_SIZE]); @@ -325,12 +328,12 @@ usprep_getProfile(const char* path, stackKey.path = (char*) path; /* fetch the data from the cache */ - umtx_lock(&usprepMutex); + umtx_lock(usprepMutex()); profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { profile->refCount++; } - umtx_unlock(&usprepMutex); + umtx_unlock(usprepMutex()); if(profile == NULL) { /* else load the data and put the data in the cache */ @@ -362,7 +365,7 @@ usprep_getProfile(const char* path, return NULL; } - umtx_lock(&usprepMutex); + umtx_lock(usprepMutex()); // If another thread already inserted the same key/value, refcount and cleanup our thread data profile = (UStringPrepProfile*) (uhash_get(SHARED_DATA_HASHTABLE,&stackKey)); if(profile != NULL) { @@ -383,7 +386,7 @@ usprep_getProfile(const char* path, profile->refCount = 1; uhash_put(SHARED_DATA_HASHTABLE, key.orphan(), profile, status); } - umtx_unlock(&usprepMutex); + umtx_unlock(usprepMutex()); } return profile; @@ -422,12 +425,12 @@ usprep_close(UStringPrepProfile* profile){ return; } - umtx_lock(&usprepMutex); + umtx_lock(usprepMutex()); /* decrement the ref count*/ if(profile->refCount > 0){ profile->refCount--; } - umtx_unlock(&usprepMutex); + umtx_unlock(usprepMutex()); } diff --git a/icu4c/source/i18n/astro.cpp b/icu4c/source/i18n/astro.cpp index bb370165208..e6dcfe895bb 100644 --- a/icu4c/source/i18n/astro.cpp +++ b/icu4c/source/i18n/astro.cpp @@ -65,7 +65,10 @@ static inline UBool isINVALID(double d) { return(uprv_isNaN(d)); } -static icu::UMutex ccLock = U_MUTEX_INITIALIZER; +static icu::UMutex *ccLock() { + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} U_CDECL_BEGIN static UBool calendar_astro_cleanup(void) { @@ -1549,12 +1552,12 @@ int32_t CalendarCache::get(CalendarCache** cache, int32_t key, UErrorCode &statu if(U_FAILURE(status)) { return 0; } - umtx_lock(&ccLock); + umtx_lock(ccLock()); if(*cache == NULL) { createCache(cache, status); if(U_FAILURE(status)) { - umtx_unlock(&ccLock); + umtx_unlock(ccLock()); return 0; } } @@ -1562,7 +1565,7 @@ int32_t CalendarCache::get(CalendarCache** cache, int32_t key, UErrorCode &statu res = uhash_igeti((*cache)->fTable, key); U_DEBUG_ASTRO_MSG(("%p: GET: [%d] == %d\n", (*cache)->fTable, key, res)); - umtx_unlock(&ccLock); + umtx_unlock(ccLock()); return res; } @@ -1570,12 +1573,12 @@ void CalendarCache::put(CalendarCache** cache, int32_t key, int32_t value, UErro if(U_FAILURE(status)) { return; } - umtx_lock(&ccLock); + umtx_lock(ccLock()); if(*cache == NULL) { createCache(cache, status); if(U_FAILURE(status)) { - umtx_unlock(&ccLock); + umtx_unlock(ccLock()); return; } } @@ -1583,7 +1586,7 @@ void CalendarCache::put(CalendarCache** cache, int32_t key, int32_t value, UErro uhash_iputi((*cache)->fTable, key, value, &status); U_DEBUG_ASTRO_MSG(("%p: PUT: [%d] := %d\n", (*cache)->fTable, key, value)); - umtx_unlock(&ccLock); + umtx_unlock(ccLock()); } CalendarCache::CalendarCache(int32_t size, UErrorCode &status) { diff --git a/icu4c/source/i18n/chnsecal.cpp b/icu4c/source/i18n/chnsecal.cpp index 69c9040bd3d..2472870f7fe 100644 --- a/icu4c/source/i18n/chnsecal.cpp +++ b/icu4c/source/i18n/chnsecal.cpp @@ -51,7 +51,10 @@ static void debug_chnsecal_msg(const char *pat, ...) // --- The cache -- -static icu::UMutex astroLock = U_MUTEX_INITIALIZER; // Protects access to gChineseCalendarAstro. +static icu::UMutex *astroLock() { // Protects access to gChineseCalendarAstro. + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} static icu::CalendarAstronomer *gChineseCalendarAstro = NULL; // Lazy Creation & Access synchronized by class CalendarCache with a mutex. @@ -535,14 +538,14 @@ int32_t ChineseCalendar::winterSolstice(int32_t gyear) const { // PST 1298 with a final result of Dec 14 10:31:59 PST 1299. double ms = daysToMillis(Grego::fieldsToDay(gyear, UCAL_DECEMBER, 1)); - umtx_lock(&astroLock); + umtx_lock(astroLock()); if(gChineseCalendarAstro == NULL) { gChineseCalendarAstro = new CalendarAstronomer(); ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup); } gChineseCalendarAstro->setTime(ms); UDate solarLong = gChineseCalendarAstro->getSunTime(CalendarAstronomer::WINTER_SOLSTICE(), TRUE); - umtx_unlock(&astroLock); + umtx_unlock(astroLock()); // Winter solstice is 270 degrees solar longitude aka Dongzhi cacheValue = (int32_t)millisToDays(solarLong); @@ -565,14 +568,14 @@ int32_t ChineseCalendar::winterSolstice(int32_t gyear) const { */ int32_t ChineseCalendar::newMoonNear(double days, UBool after) const { - umtx_lock(&astroLock); + umtx_lock(astroLock()); if(gChineseCalendarAstro == NULL) { gChineseCalendarAstro = new CalendarAstronomer(); ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup); } gChineseCalendarAstro->setTime(daysToMillis(days)); UDate newMoon = gChineseCalendarAstro->getMoonTime(CalendarAstronomer::NEW_MOON(), after); - umtx_unlock(&astroLock); + umtx_unlock(astroLock()); return (int32_t) millisToDays(newMoon); } @@ -597,14 +600,14 @@ int32_t ChineseCalendar::synodicMonthsBetween(int32_t day1, int32_t day2) const */ int32_t ChineseCalendar::majorSolarTerm(int32_t days) const { - umtx_lock(&astroLock); + umtx_lock(astroLock()); if(gChineseCalendarAstro == NULL) { gChineseCalendarAstro = new CalendarAstronomer(); ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup); } gChineseCalendarAstro->setTime(daysToMillis(days)); UDate solarLongitude = gChineseCalendarAstro->getSunLongitude(); - umtx_unlock(&astroLock); + umtx_unlock(astroLock()); // Compute (floor(solarLongitude / (pi/6)) + 2) % 12 int32_t term = ( ((int32_t)(6 * solarLongitude / CalendarAstronomer::PI)) + 2 ) % 12; diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp index ae7d2928ae3..42cf5c5e621 100644 --- a/icu4c/source/i18n/dtfmtsym.cpp +++ b/icu4c/source/i18n/dtfmtsym.cpp @@ -235,8 +235,6 @@ static const char gDayPeriodTag[]="dayPeriod"; static const char gContextTransformsTag[]="contextTransforms"; -static UMutex LOCK = U_MUTEX_INITIALIZER; - /** * Jitterbug 2974: MSVC has a bug whereby new X[0] behaves badly. * Work around this. @@ -1248,6 +1246,7 @@ const UnicodeString** DateFormatSymbols::getZoneStrings(int32_t& rowCount, int32_t& columnCount) const { const UnicodeString **result = NULL; + static UMutex LOCK = U_MUTEX_INITIALIZER; umtx_lock(&LOCK); if (fZoneStrings == NULL) { diff --git a/icu4c/source/i18n/dtitvfmt.cpp b/icu4c/source/i18n/dtitvfmt.cpp index 1de7652335b..93ceff3b5ac 100644 --- a/icu4c/source/i18n/dtitvfmt.cpp +++ b/icu4c/source/i18n/dtitvfmt.cpp @@ -82,7 +82,10 @@ UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DateIntervalFormat) // Mutex, protects access to fDateFormat, fFromCalendar and fToCalendar. // Needed because these data members are modified by const methods of DateIntervalFormat. -static UMutex gFormatterMutex = U_MUTEX_INITIALIZER; +static UMutex *gFormatterMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} DateIntervalFormat* U_EXPORT2 DateIntervalFormat::createInstance(const UnicodeString& skeleton, @@ -168,7 +171,7 @@ DateIntervalFormat::operator=(const DateIntervalFormat& itvfmt) { delete fTimePattern; delete fDateTimeFormat; { - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); if ( itvfmt.fDateFormat ) { fDateFormat = (SimpleDateFormat*)itvfmt.fDateFormat->clone(); } else { @@ -230,7 +233,7 @@ DateIntervalFormat::operator==(const Format& other) const { if ((fInfo != fmt->fInfo) && (fInfo == NULL || fmt->fInfo == NULL)) {return FALSE;} if (fInfo && fmt->fInfo && (*fInfo != *fmt->fInfo )) {return FALSE;} { - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); if (fDateFormat != fmt->fDateFormat && (fDateFormat == NULL || fmt->fDateFormat == NULL)) {return FALSE;} if (fDateFormat && fmt->fDateFormat && (*fDateFormat != *fmt->fDateFormat)) {return FALSE;} } @@ -292,7 +295,7 @@ DateIntervalFormat::format(const DateInterval* dtInterval, handler.setAcceptFirstOnly(TRUE); int8_t ignore; - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); return formatIntervalImpl(*dtInterval, appendTo, ignore, handler, status); } @@ -309,7 +312,7 @@ FormattedDateInterval DateIntervalFormat::formatToValue( auto handler = result->getHandler(status); handler.setCategory(UFIELD_CATEGORY_DATE); { - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); formatIntervalImpl(dtInterval, string, firstIndex, handler, status); } handler.getError(status); @@ -341,7 +344,7 @@ DateIntervalFormat::format(Calendar& fromCalendar, handler.setAcceptFirstOnly(TRUE); int8_t ignore; - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); return formatImpl(fromCalendar, toCalendar, appendTo, ignore, handler, status); } @@ -359,7 +362,7 @@ FormattedDateInterval DateIntervalFormat::formatToValue( auto handler = result->getHandler(status); handler.setCategory(UFIELD_CATEGORY_DATE); { - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); formatImpl(fromCalendar, toCalendar, string, firstIndex, handler, status); } handler.getError(status); @@ -597,7 +600,7 @@ const TimeZone& DateIntervalFormat::getTimeZone() const { if (fDateFormat != NULL) { - Mutex lock(&gFormatterMutex); + Mutex lock(gFormatterMutex()); return fDateFormat->getTimeZone(); } // If fDateFormat is NULL (unexpected), create default timezone. diff --git a/icu4c/source/i18n/gender.cpp b/icu4c/source/i18n/gender.cpp index 1456d86276f..50161e1468d 100644 --- a/icu4c/source/i18n/gender.cpp +++ b/icu4c/source/i18n/gender.cpp @@ -32,7 +32,7 @@ #include "uhash.h" static UHashtable* gGenderInfoCache = NULL; -static icu::UMutex gGenderMetaLock = U_MUTEX_INITIALIZER; + static const char* gNeutralStr = "neutral"; static const char* gMailTaintsStr = "maleTaints"; static const char* gMixedNeutralStr = "mixedNeutral"; @@ -98,6 +98,7 @@ const GenderInfo* GenderInfo::getInstance(const Locale& locale, UErrorCode& stat return NULL; } + static UMutex gGenderMetaLock = U_MUTEX_INITIALIZER; const GenderInfo* result = NULL; const char* key = locale.getName(); { diff --git a/icu4c/source/i18n/islamcal.cpp b/icu4c/source/i18n/islamcal.cpp index a002262971a..a024f4cbfa2 100644 --- a/icu4c/source/i18n/islamcal.cpp +++ b/icu4c/source/i18n/islamcal.cpp @@ -54,7 +54,6 @@ static void debug_islamcal_msg(const char *pat, ...) // --- The cache -- // cache of months -static icu::UMutex astroLock = U_MUTEX_INITIALIZER; // pod bay door lock static icu::CalendarCache *gMonthCache = NULL; static icu::CalendarAstronomer *gIslamicCalendarAstro = NULL; @@ -471,6 +470,7 @@ double IslamicCalendar::moonAge(UDate time, UErrorCode &status) { double age = 0; + static UMutex astroLock = U_MUTEX_INITIALIZER; // pod bay door lock umtx_lock(&astroLock); if(gIslamicCalendarAstro == NULL) { gIslamicCalendarAstro = new CalendarAstronomer(); diff --git a/icu4c/source/i18n/listformatter.cpp b/icu4c/source/i18n/listformatter.cpp index ab8ef14311e..802ab0ef782 100644 --- a/icu4c/source/i18n/listformatter.cpp +++ b/icu4c/source/i18n/listformatter.cpp @@ -80,7 +80,6 @@ UPRV_FORMATTED_VALUE_SUBCLASS_AUTO_IMPL(FormattedList) static Hashtable* listPatternHash = nullptr; -static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; static const char STANDARD_STYLE[] = "standard"; U_CDECL_BEGIN @@ -145,6 +144,7 @@ const ListFormatInternal* ListFormatter::getListFormatInternal( keyBuffer.append(':', errorCode).append(style, errorCode); UnicodeString key(keyBuffer.data(), -1, US_INV); ListFormatInternal* result = nullptr; + static UMutex listFormatterMutex = U_MUTEX_INITIALIZER; { Mutex m(&listFormatterMutex); if (listPatternHash == nullptr) { diff --git a/icu4c/source/i18n/numfmt.cpp b/icu4c/source/i18n/numfmt.cpp index 4b2eaac6147..7adf902df47 100644 --- a/icu4c/source/i18n/numfmt.cpp +++ b/icu4c/source/i18n/numfmt.cpp @@ -156,7 +156,6 @@ static const icu::number::impl::CldrPatternStyle gFormatCldrStyles[UNUM_FORMAT_S // Static hashtable cache of NumberingSystem objects used by NumberFormat static UHashtable * NumberingSystem_cache = NULL; -static icu::UMutex nscacheMutex = U_MUTEX_INITIALIZER; static icu::UInitOnce gNSCacheInitOnce = U_INITONCE_INITIALIZER; #if !UCONFIG_NO_SERVICE @@ -1363,6 +1362,7 @@ NumberFormat::makeInstance(const Locale& desiredLocale, // TODO: Bad hash key usage, see ticket #8504. int32_t hashKey = desiredLocale.hashCode(); + static icu::UMutex nscacheMutex = U_MUTEX_INITIALIZER; Mutex lock(&nscacheMutex); ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey); if (ns == NULL) { diff --git a/icu4c/source/i18n/rbt.cpp b/icu4c/source/i18n/rbt.cpp index 9cb1b0e9a70..b4407930d86 100644 --- a/icu4c/source/i18n/rbt.cpp +++ b/icu4c/source/i18n/rbt.cpp @@ -27,7 +27,6 @@ U_NAMESPACE_BEGIN UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTransliterator) -static UMutex transliteratorDataMutex = U_MUTEX_INITIALIZER; static Replaceable *gLockedText = NULL; void RuleBasedTransliterator::_construct(const UnicodeString& rules, @@ -253,6 +252,8 @@ RuleBasedTransliterator::handleTransliterate(Replaceable& text, UTransPosition& // Shared RBT data protected by transliteratorDataMutex. // // TODO(andy): Need a better scheme for handling this. + + static UMutex transliteratorDataMutex = U_MUTEX_INITIALIZER; UBool needToLock; { Mutex m; diff --git a/icu4c/source/i18n/rbtz.cpp b/icu4c/source/i18n/rbtz.cpp index d98613fe99a..4aa143c706b 100644 --- a/icu4c/source/i18n/rbtz.cpp +++ b/icu4c/source/i18n/rbtz.cpp @@ -146,10 +146,10 @@ RuleBasedTimeZone::addTransitionRule(TimeZoneRule* rule, UErrorCode& status) { fUpToDate = FALSE; } -static UMutex gLock = U_MUTEX_INITIALIZER; void RuleBasedTimeZone::completeConst(UErrorCode& status) const { + static UMutex gLock = U_MUTEX_INITIALIZER; if (U_FAILURE(status)) { return; } diff --git a/icu4c/source/i18n/reldatefmt.cpp b/icu4c/source/i18n/reldatefmt.cpp index 4f6f7233ddb..2b58e47c257 100644 --- a/icu4c/source/i18n/reldatefmt.cpp +++ b/icu4c/source/i18n/reldatefmt.cpp @@ -51,8 +51,6 @@ // Copied from uscript_props.cpp -static icu::UMutex gBrkIterMutex = U_MUTEX_INITIALIZER; - U_NAMESPACE_BEGIN // RelativeDateTimeFormatter specific data for a single locale @@ -1186,6 +1184,7 @@ UnicodeString& RelativeDateTimeFormatter::adjustForContext(UnicodeString &str) c // Must guarantee that one thread at a time accesses the shared break // iterator. + static icu::UMutex gBrkIterMutex = U_MUTEX_INITIALIZER; Mutex lock(&gBrkIterMutex); str.toTitle( fOptBreakIterator->get(), diff --git a/icu4c/source/i18n/simpletz.cpp b/icu4c/source/i18n/simpletz.cpp index 57a7ba8ed75..cacfa187cfc 100644 --- a/icu4c/source/i18n/simpletz.cpp +++ b/icu4c/source/i18n/simpletz.cpp @@ -1077,13 +1077,13 @@ SimpleTimeZone::deleteTransitionRules(void) { * allocate it in the constructors. This would be a more intrusive change, but doable * if performance turns out to be an issue. */ -static UMutex gLock = U_MUTEX_INITIALIZER; void SimpleTimeZone::checkTransitionRules(UErrorCode& status) const { if (U_FAILURE(status)) { return; } + static UMutex gLock = U_MUTEX_INITIALIZER; umtx_lock(&gLock); if (!transitionRulesInitialized) { SimpleTimeZone *ncThis = const_cast(this); diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp index 9ab765791fb..be0ced53987 100644 --- a/icu4c/source/i18n/smpdtfmt.cpp +++ b/icu4c/source/i18n/smpdtfmt.cpp @@ -230,7 +230,10 @@ 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 UMutex LOCK = U_MUTEX_INITIALIZER; +static UMutex *LOCK() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} UOBJECT_DEFINE_RTTI_IMPLEMENTATION(SimpleDateFormat) @@ -1263,14 +1266,14 @@ SimpleDateFormat::initNumberFormatters(const Locale &locale,UErrorCode &status) if ( fDateOverride.isBogus() && fTimeOverride.isBogus() ) { return; } - umtx_lock(&LOCK); + umtx_lock(LOCK()); if (fSharedNumberFormatters == NULL) { fSharedNumberFormatters = allocSharedNumberFormatters(); if (fSharedNumberFormatters == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } } - umtx_unlock(&LOCK); + umtx_unlock(LOCK()); if (U_FAILURE(status)) { return; @@ -4198,7 +4201,7 @@ SimpleDateFormat::skipUWhiteSpace(const UnicodeString& text, int32_t pos) const TimeZoneFormat * SimpleDateFormat::tzFormat(UErrorCode &status) const { if (fTimeZoneFormat == NULL) { - umtx_lock(&LOCK); + umtx_lock(LOCK()); { if (fTimeZoneFormat == NULL) { TimeZoneFormat *tzfmt = TimeZoneFormat::createInstance(fLocale, status); @@ -4209,7 +4212,7 @@ SimpleDateFormat::tzFormat(UErrorCode &status) const { const_cast(this)->fTimeZoneFormat = tzfmt; } } - umtx_unlock(&LOCK); + umtx_unlock(LOCK()); } return fTimeZoneFormat; } diff --git a/icu4c/source/i18n/translit.cpp b/icu4c/source/i18n/translit.cpp index 59025be17bd..7d9c7192e29 100644 --- a/icu4c/source/i18n/translit.cpp +++ b/icu4c/source/i18n/translit.cpp @@ -91,7 +91,10 @@ static const char RB_RULE_BASED_IDS[] = "RuleBasedTransliteratorIDs"; /** * The mutex controlling access to registry object. */ -static icu::UMutex registryMutex = U_MUTEX_INITIALIZER; +static icu::UMutex *registryMutex() { + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} /** * System transliterator registry; non-null when initialized. @@ -978,11 +981,11 @@ Transliterator* Transliterator::createBasicInstance(const UnicodeString& id, TransliteratorAlias* alias = 0; Transliterator* t = 0; - umtx_lock(®istryMutex); + umtx_lock(registryMutex()); if (HAVE_REGISTRY(ec)) { t = registry->get(id, alias, ec); } - umtx_unlock(®istryMutex); + umtx_unlock(registryMutex()); if (U_FAILURE(ec)) { delete t; @@ -1010,11 +1013,11 @@ Transliterator* Transliterator::createBasicInstance(const UnicodeString& id, alias = 0; // Step 2. reget - umtx_lock(®istryMutex); + umtx_lock(registryMutex()); if (HAVE_REGISTRY(ec)) { t = registry->reget(id, parser, alias, ec); } - umtx_unlock(®istryMutex); + umtx_unlock(registryMutex()); // Step 3. Loop back around! } else { @@ -1212,7 +1215,7 @@ UnicodeSet& Transliterator::getTargetSet(UnicodeSet& result) const { void U_EXPORT2 Transliterator::registerFactory(const UnicodeString& id, Transliterator::Factory factory, Transliterator::Token context) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _registerFactory(id, factory, context); @@ -1251,7 +1254,7 @@ void Transliterator::_registerSpecialInverse(const UnicodeString& target, * @see #unregister */ void U_EXPORT2 Transliterator::registerInstance(Transliterator* adoptedPrototype) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _registerInstance(adoptedPrototype); @@ -1265,7 +1268,7 @@ void Transliterator::_registerInstance(Transliterator* adoptedPrototype) { void U_EXPORT2 Transliterator::registerAlias(const UnicodeString& aliasID, const UnicodeString& realID) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _registerAlias(aliasID, realID); @@ -1287,7 +1290,7 @@ void Transliterator::_registerAlias(const UnicodeString& aliasID, */ void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { registry->remove(ID); @@ -1302,7 +1305,7 @@ void U_EXPORT2 Transliterator::unregister(const UnicodeString& ID) { */ int32_t U_EXPORT2 Transliterator::countAvailableIDs(void) { int32_t retVal = 0; - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { retVal = registry->countAvailableIDs(); @@ -1318,12 +1321,12 @@ int32_t U_EXPORT2 Transliterator::countAvailableIDs(void) { */ const UnicodeString& U_EXPORT2 Transliterator::getAvailableID(int32_t index) { const UnicodeString* result = NULL; - umtx_lock(®istryMutex); + umtx_lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { result = ®istry->getAvailableID(index); } - umtx_unlock(®istryMutex); + umtx_unlock(registryMutex()); U_ASSERT(result != NULL); // fail if no registry return *result; } @@ -1331,11 +1334,11 @@ const UnicodeString& U_EXPORT2 Transliterator::getAvailableID(int32_t index) { StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) { if (U_FAILURE(ec)) return NULL; StringEnumeration* result = NULL; - umtx_lock(®istryMutex); + umtx_lock(registryMutex()); if (HAVE_REGISTRY(ec)) { result = registry->getAvailableIDs(); } - umtx_unlock(®istryMutex); + umtx_unlock(registryMutex()); if (result == NULL) { ec = U_INTERNAL_TRANSLITERATOR_ERROR; } @@ -1343,14 +1346,14 @@ StringEnumeration* U_EXPORT2 Transliterator::getAvailableIDs(UErrorCode& ec) { } int32_t U_EXPORT2 Transliterator::countAvailableSources(void) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; return HAVE_REGISTRY(ec) ? _countAvailableSources() : 0; } UnicodeString& U_EXPORT2 Transliterator::getAvailableSource(int32_t index, UnicodeString& result) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _getAvailableSource(index, result); @@ -1359,7 +1362,7 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableSource(int32_t index, } int32_t U_EXPORT2 Transliterator::countAvailableTargets(const UnicodeString& source) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; return HAVE_REGISTRY(ec) ? _countAvailableTargets(source) : 0; } @@ -1367,7 +1370,7 @@ int32_t U_EXPORT2 Transliterator::countAvailableTargets(const UnicodeString& sou UnicodeString& U_EXPORT2 Transliterator::getAvailableTarget(int32_t index, const UnicodeString& source, UnicodeString& result) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _getAvailableTarget(index, source, result); @@ -1377,7 +1380,7 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableTarget(int32_t index, int32_t U_EXPORT2 Transliterator::countAvailableVariants(const UnicodeString& source, const UnicodeString& target) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; return HAVE_REGISTRY(ec) ? _countAvailableVariants(source, target) : 0; } @@ -1386,7 +1389,7 @@ UnicodeString& U_EXPORT2 Transliterator::getAvailableVariant(int32_t index, const UnicodeString& source, const UnicodeString& target, UnicodeString& result) { - Mutex lock(®istryMutex); + Mutex lock(registryMutex()); UErrorCode ec = U_ZERO_ERROR; if (HAVE_REGISTRY(ec)) { _getAvailableVariant(index, source, target, result); diff --git a/icu4c/source/i18n/tridpars.cpp b/icu4c/source/i18n/tridpars.cpp index b27663649ad..f54393b6fa5 100644 --- a/icu4c/source/i18n/tridpars.cpp +++ b/icu4c/source/i18n/tridpars.cpp @@ -50,7 +50,10 @@ static UInitOnce gSpecialInversesInitOnce = U_INITONCE_INITIALIZER; /** * The mutex controlling access to SPECIAL_INVERSES */ -static UMutex LOCK = U_MUTEX_INITIALIZER; +static UMutex *LOCK() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} TransliteratorIDParser::Specs::Specs(const UnicodeString& s, const UnicodeString& t, const UnicodeString& v, UBool sawS, @@ -659,7 +662,7 @@ void TransliteratorIDParser::registerSpecialInverse(const UnicodeString& target, bidirectional = FALSE; } - Mutex lock(&LOCK); + Mutex lock(LOCK()); UnicodeString *tempus = new UnicodeString(inverseTarget); // Used for null pointer check before usage. if (tempus == NULL) { @@ -863,9 +866,9 @@ TransliteratorIDParser::specsToSpecialInverse(const Specs& specs, UErrorCode &st UnicodeString* inverseTarget; - umtx_lock(&LOCK); + umtx_lock(LOCK()); inverseTarget = (UnicodeString*) SPECIAL_INVERSES->get(specs.target); - umtx_unlock(&LOCK); + umtx_unlock(LOCK()); if (inverseTarget != NULL) { // If the original ID contained "Any-" then make the diff --git a/icu4c/source/i18n/tzfmt.cpp b/icu4c/source/i18n/tzfmt.cpp index 4730455ac4e..5aa7af5b329 100644 --- a/icu4c/source/i18n/tzfmt.cpp +++ b/icu4c/source/i18n/tzfmt.cpp @@ -147,7 +147,10 @@ static icu::UInitOnce gZoneIdTrieInitOnce = U_INITONCE_INITIALIZER; static TextTrieMap *gShortZoneIdTrie = NULL; static icu::UInitOnce gShortZoneIdTrieInitOnce = U_INITONCE_INITIALIZER; -static UMutex gLock = U_MUTEX_INITIALIZER; +static UMutex *gLock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} U_CDECL_BEGIN /** @@ -1382,12 +1385,12 @@ TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const { return NULL; } - umtx_lock(&gLock); + umtx_lock(gLock()); if (fTimeZoneGenericNames == NULL) { TimeZoneFormat *nonConstThis = const_cast(this); nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status); } - umtx_unlock(&gLock); + umtx_unlock(gLock()); return fTimeZoneGenericNames; } @@ -1398,7 +1401,7 @@ TimeZoneFormat::getTZDBTimeZoneNames(UErrorCode& status) const { return NULL; } - umtx_lock(&gLock); + umtx_lock(gLock()); if (fTZDBTimeZoneNames == NULL) { TZDBTimeZoneNames *tzdbNames = new TZDBTimeZoneNames(fLocale); if (tzdbNames == NULL) { @@ -1408,7 +1411,7 @@ TimeZoneFormat::getTZDBTimeZoneNames(UErrorCode& status) const { nonConstThis->fTZDBTimeZoneNames = tzdbNames; } } - umtx_unlock(&gLock); + umtx_unlock(gLock()); return fTZDBTimeZoneNames; } diff --git a/icu4c/source/i18n/tzgnames.cpp b/icu4c/source/i18n/tzgnames.cpp index 5f5b7db3022..4e3ecb4c607 100644 --- a/icu4c/source/i18n/tzgnames.cpp +++ b/icu4c/source/i18n/tzgnames.cpp @@ -269,7 +269,10 @@ GNameSearchHandler::getMatches(int32_t& maxMatchLen) { return results; } -static UMutex gLock = U_MUTEX_INITIALIZER; +static UMutex *gLock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} class TZGNCore : public UMemory { public: @@ -485,11 +488,11 @@ TZGNCore::getGenericLocationName(const UnicodeString& tzCanonicalID, UnicodeStri const UChar *locname = NULL; TZGNCore *nonConstThis = const_cast(this); - umtx_lock(&gLock); + umtx_lock(gLock()); { locname = nonConstThis->getGenericLocationName(tzCanonicalID); } - umtx_unlock(&gLock); + umtx_unlock(gLock()); if (locname == NULL) { name.setToBogus(); @@ -740,11 +743,11 @@ TZGNCore::getPartialLocationName(const UnicodeString& tzCanonicalID, const UChar *uplname = NULL; TZGNCore *nonConstThis = const_cast(this); - umtx_lock(&gLock); + umtx_lock(gLock()); { uplname = nonConstThis->getPartialLocationName(tzCanonicalID, mzID, isLong, mzDisplayName); } - umtx_unlock(&gLock); + umtx_unlock(gLock()); if (uplname == NULL) { name.setToBogus(); @@ -1007,11 +1010,11 @@ TZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UE TZGNCore *nonConstThis = const_cast(this); - umtx_lock(&gLock); + umtx_lock(gLock()); { fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); } - umtx_unlock(&gLock); + umtx_unlock(gLock()); if (U_FAILURE(status)) { return NULL; @@ -1038,7 +1041,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(&gLock); + umtx_lock(gLock()); { if (!fGNamesTrieFullyLoaded) { StringEnumeration *tzIDs = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status); @@ -1060,18 +1063,18 @@ TZGNCore::findLocal(const UnicodeString& text, int32_t start, uint32_t types, UE } } } - umtx_unlock(&gLock); + umtx_unlock(gLock()); if (U_FAILURE(status)) { return NULL; } - umtx_lock(&gLock); + umtx_lock(gLock()); { // now try it again fGNamesTrie.search(text, start, (TextTrieMapSearchResultHandler *)&handler, status); } - umtx_unlock(&gLock); + umtx_unlock(gLock()); results = handler.getMatches(maxLen); if (results != NULL && maxLen > 0) { @@ -1112,7 +1115,10 @@ typedef struct TZGNCoreRef { } TZGNCoreRef; // TZGNCore object cache handling -static UMutex gTZGNLock = U_MUTEX_INITIALIZER; +static UMutex *gTZGNLock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} static UHashtable *gTZGNCoreCache = NULL; static UBool gTZGNCoreCacheInitialized = FALSE; @@ -1178,13 +1184,13 @@ TimeZoneGenericNames::TimeZoneGenericNames() } TimeZoneGenericNames::~TimeZoneGenericNames() { - umtx_lock(&gTZGNLock); + umtx_lock(gTZGNLock()); { U_ASSERT(fRef->refCount > 0); // Just decrement the reference count fRef->refCount--; } - umtx_unlock(&gTZGNLock); + umtx_unlock(gTZGNLock()); } TimeZoneGenericNames* @@ -1200,7 +1206,7 @@ TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) { TZGNCoreRef *cacheEntry = NULL; { - Mutex lock(&gTZGNLock); + Mutex lock(gTZGNLock()); if (!gTZGNCoreCacheInitialized) { // Create empty hashtable @@ -1292,13 +1298,13 @@ TimeZoneGenericNames* TimeZoneGenericNames::clone() const { TimeZoneGenericNames* other = new TimeZoneGenericNames(); if (other) { - umtx_lock(&gTZGNLock); + umtx_lock(gTZGNLock()); { // Just increments the reference count fRef->refCount++; other->fRef = fRef; } - umtx_unlock(&gTZGNLock); + umtx_unlock(gTZGNLock()); } return other; } diff --git a/icu4c/source/i18n/tznames.cpp b/icu4c/source/i18n/tznames.cpp index 5a79c22aacf..36d27ca699b 100644 --- a/icu4c/source/i18n/tznames.cpp +++ b/icu4c/source/i18n/tznames.cpp @@ -29,7 +29,10 @@ U_NAMESPACE_BEGIN // TimeZoneNames object cache handling -static UMutex gTimeZoneNamesLock = U_MUTEX_INITIALIZER; +static UMutex *gTimeZoneNamesLock() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} static UHashtable *gTimeZoneNamesCache = NULL; static UBool gTimeZoneNamesCacheInitialized = FALSE; @@ -132,7 +135,7 @@ TimeZoneNamesDelegate::TimeZoneNamesDelegate() } TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status) { - Mutex lock(&gTimeZoneNamesLock); + Mutex lock(gTimeZoneNamesLock()); if (!gTimeZoneNamesCacheInitialized) { // Create empty hashtable if it is not already initialized. gTimeZoneNamesCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); @@ -208,7 +211,7 @@ TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& s } TimeZoneNamesDelegate::~TimeZoneNamesDelegate() { - umtx_lock(&gTimeZoneNamesLock); + umtx_lock(gTimeZoneNamesLock()); { if (fTZnamesCacheEntry) { U_ASSERT(fTZnamesCacheEntry->refCount > 0); @@ -216,7 +219,7 @@ TimeZoneNamesDelegate::~TimeZoneNamesDelegate() { fTZnamesCacheEntry->refCount--; } } - umtx_unlock(&gTimeZoneNamesLock); + umtx_unlock(gTimeZoneNamesLock()); } UBool @@ -237,13 +240,13 @@ TimeZoneNames* TimeZoneNamesDelegate::clone() const { TimeZoneNamesDelegate* other = new TimeZoneNamesDelegate(); if (other != NULL) { - umtx_lock(&gTimeZoneNamesLock); + umtx_lock(gTimeZoneNamesLock()); { // Just increment the reference count fTZnamesCacheEntry->refCount++; other->fTZnamesCacheEntry = fTZnamesCacheEntry; } - umtx_unlock(&gTimeZoneNamesLock); + umtx_unlock(gTimeZoneNamesLock()); } return other; } diff --git a/icu4c/source/i18n/tznames_impl.cpp b/icu4c/source/i18n/tznames_impl.cpp index 7bfbc04e180..5e3b478c28f 100644 --- a/icu4c/source/i18n/tznames_impl.cpp +++ b/icu4c/source/i18n/tznames_impl.cpp @@ -49,8 +49,10 @@ static const UChar NO_NAME[] = { 0 }; // for empty no-fallback time static const char* TZDBNAMES_KEYS[] = {"ss", "sd"}; static const int32_t TZDBNAMES_KEYS_SIZE = UPRV_LENGTHOF(TZDBNAMES_KEYS); -static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER; -static UMutex gDataMutex = U_MUTEX_INITIALIZER; +static UMutex *gDataMutex() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} static UHashtable* gTZDBNamesMap = NULL; static icu::UInitOnce gTZDBNamesMapInitOnce = U_INITONCE_INITIALIZER; @@ -357,8 +359,6 @@ TextTrieMap::getChildNode(CharacterNode *parent, UChar c) const { return NULL; } -// Mutex for protecting the lazy creation of the Trie node structure on the first call to search(). -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 @@ -386,6 +386,10 @@ TextTrieMap::search(const UnicodeString &text, int32_t start, // the ICU atomic safe functions for assigning and testing. // Don't test the pointer fLazyContents. // Don't do unless it's really required. + + // Mutex for protecting the lazy creation of the Trie node structure on the first call to search(). + static UMutex TextTrieMutex = U_MUTEX_INITIALIZER; + Mutex lock(&TextTrieMutex); if (fLazyContents != NULL) { TextTrieMap *nonConstThis = const_cast(this); @@ -1210,7 +1214,7 @@ TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID, TimeZoneNamesImpl *nonConstThis = const_cast(this); { - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); UErrorCode status = U_ZERO_ERROR; znames = nonConstThis->loadMetaZoneNames(mzID, status); if (U_FAILURE(status)) { return name; } @@ -1236,7 +1240,7 @@ TimeZoneNamesImpl::getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNa TimeZoneNamesImpl *nonConstThis = const_cast(this); { - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); UErrorCode status = U_ZERO_ERROR; tznames = nonConstThis->loadTimeZoneNames(tzID, status); if (U_FAILURE(status)) { return name; } @@ -1259,7 +1263,7 @@ TimeZoneNamesImpl::getExemplarLocationName(const UnicodeString& tzID, UnicodeStr TimeZoneNamesImpl *nonConstThis = const_cast(this); { - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); UErrorCode status = U_ZERO_ERROR; tznames = nonConstThis->loadTimeZoneNames(tzID, status); if (U_FAILURE(status)) { return name; } @@ -1354,7 +1358,7 @@ TimeZoneNamesImpl::find(const UnicodeString& text, int32_t start, uint32_t types // Synchronize so that data is not loaded multiple times. // TODO: Consider more fine-grained synchronization. { - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); // First try of lookup. matches = doFind(handler, text, start, status); @@ -1581,7 +1585,7 @@ void TimeZoneNamesImpl::loadAllDisplayNames(UErrorCode& status) { if (U_FAILURE(status)) return; { - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); internalLoadAllDisplayNames(status); } } @@ -1598,7 +1602,7 @@ void TimeZoneNamesImpl::getDisplayNames(const UnicodeString& tzID, // Load the time zone strings { - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); tznames = (void*) nonConstThis->loadTimeZoneNames(tzID, status); if (U_FAILURE(status)) { return; } } @@ -1618,7 +1622,7 @@ void TimeZoneNamesImpl::getDisplayNames(const UnicodeString& tzID, } else { // Load the meta zone strings // Mutex is scoped to the "else" statement - Mutex lock(&gDataMutex); + Mutex lock(gDataMutex()); mznames = (void*) nonConstThis->loadMetaZoneNames(mzID, status); if (U_FAILURE(status)) { return; } // Note: when the metazone doesn't exist, in Java, loadMetaZoneNames returns @@ -2243,6 +2247,7 @@ TZDBTimeZoneNames::getMetaZoneNames(const UnicodeString& mzID, UErrorCode& statu U_ASSERT(status == U_ZERO_ERROR); // already checked length above mzIDKey[mzID.length()] = 0; + static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER; umtx_lock(&gTZDBNamesMapLock); { void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey); diff --git a/icu4c/source/i18n/zonemeta.cpp b/icu4c/source/i18n/zonemeta.cpp index ddc8e296221..0e3ee893161 100644 --- a/icu4c/source/i18n/zonemeta.cpp +++ b/icu4c/source/i18n/zonemeta.cpp @@ -30,7 +30,10 @@ #include "olsontz.h" #include "uinvchar.h" -static icu::UMutex gZoneMetaLock = U_MUTEX_INITIALIZER; +static icu::UMutex *gZoneMetaLock() { + static icu::UMutex m = U_MUTEX_INITIALIZER; + return &m; +} // CLDR Canonical ID mapping table static UHashtable *gCanonicalIDCache = NULL; @@ -263,11 +266,11 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { } // Check if it was already cached - umtx_lock(&gZoneMetaLock); + umtx_lock(gZoneMetaLock()); { canonicalID = (const UChar *)uhash_get(gCanonicalIDCache, utzid); } - umtx_unlock(&gZoneMetaLock); + umtx_unlock(gZoneMetaLock()); if (canonicalID != NULL) { return canonicalID; @@ -348,7 +351,7 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { U_ASSERT(canonicalID != NULL); // canocanilD must be non-NULL here // Put the resolved canonical ID to the cache - umtx_lock(&gZoneMetaLock); + umtx_lock(gZoneMetaLock()); { const UChar* idInCache = (const UChar *)uhash_get(gCanonicalIDCache, utzid); if (idInCache == NULL) { @@ -368,7 +371,7 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { } } } - umtx_unlock(&gZoneMetaLock); + umtx_unlock(gZoneMetaLock()); } return canonicalID; @@ -446,14 +449,14 @@ ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, // Check if it was already cached UBool cached = FALSE; UBool singleZone = FALSE; - umtx_lock(&gZoneMetaLock); + umtx_lock(gZoneMetaLock()); { singleZone = cached = gSingleZoneCountries->contains((void*)region); if (!cached) { cached = gMultiZonesCountries->contains((void*)region); } } - umtx_unlock(&gZoneMetaLock); + umtx_unlock(gZoneMetaLock()); if (!cached) { // We need to go through all zones associated with the region. @@ -472,7 +475,7 @@ ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, delete ids; // Cache the result - umtx_lock(&gZoneMetaLock); + umtx_lock(gZoneMetaLock()); { UErrorCode ec = U_ZERO_ERROR; if (singleZone) { @@ -485,7 +488,7 @@ ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, } } } - umtx_unlock(&gZoneMetaLock); + umtx_unlock(gZoneMetaLock()); } if (singleZone) { @@ -572,11 +575,11 @@ ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { // get the mapping from cache const UVector *result = NULL; - umtx_lock(&gZoneMetaLock); + umtx_lock(gZoneMetaLock()); { result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); } - umtx_unlock(&gZoneMetaLock); + umtx_unlock(gZoneMetaLock()); if (result != NULL) { return result; @@ -590,7 +593,7 @@ ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { } // put the new one into the cache - umtx_lock(&gZoneMetaLock); + umtx_lock(gZoneMetaLock()); { // make sure it's already created result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); @@ -618,7 +621,7 @@ ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { delete tmpResult; } } - umtx_unlock(&gZoneMetaLock); + umtx_unlock(gZoneMetaLock()); return result; } diff --git a/icu4c/source/io/locbund.cpp b/icu4c/source/io/locbund.cpp index b239be65087..c4ef1952e5f 100644 --- a/icu4c/source/io/locbund.cpp +++ b/icu4c/source/io/locbund.cpp @@ -45,9 +45,9 @@ static UBool U_CALLCONV locbund_cleanup(void) { } U_CDECL_END -static icu::UMutex gLock = U_MUTEX_INITIALIZER; static inline UNumberFormat * copyInvariantFormatter(ULocaleBundle *result, UNumberFormatStyle style) { U_NAMESPACE_USE + static UMutex gLock = U_MUTEX_INITIALIZER; Mutex lock(&gLock); if (result->fNumberFormat[style-1] == NULL) { if (gPosixNumberFormat[style-1] == NULL) { diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp index 0cbf12ee416..201c5460ec6 100644 --- a/icu4c/source/test/intltest/intltest.cpp +++ b/icu4c/source/test/intltest/intltest.cpp @@ -1109,7 +1109,6 @@ UBool IntlTest::printKnownIssues() } } -static UMutex messageMutex = U_MUTEX_INITIALIZER; void IntlTest::LL_message( UnicodeString message, UBool newline ) { @@ -1117,6 +1116,7 @@ void IntlTest::LL_message( UnicodeString message, UBool newline ) // All error messages generated by tests funnel through here. // Multithreaded tests can concurrently generate errors, requiring synchronization // to keep each message together. + static UMutex messageMutex = U_MUTEX_INITIALIZER; Mutex lock(&messageMutex); // string that starts with a LineFeed character and continues diff --git a/icu4c/source/test/intltest/tsmthred.cpp b/icu4c/source/test/intltest/tsmthred.cpp index 9126100d11c..2c7528feab9 100644 --- a/icu4c/source/test/intltest/tsmthred.cpp +++ b/icu4c/source/test/intltest/tsmthred.cpp @@ -240,8 +240,14 @@ void MultithreadTest::TestArabicShapingThreads() // platform's mutex support is at least superficially there. // //---------------------------------------------------------------------- -static UMutex gTestMutexA = U_MUTEX_INITIALIZER; -static UConditionVar gThreadsCountChanged = U_CONDITION_INITIALIZER; +static UMutex *gTestMutexA() { + static UMutex m = U_MUTEX_INITIALIZER; + return &m; +} +static UConditionVar *gThreadsCountChanged() { + static UConditionVar cv = U_CONDITION_INITIALIZER; + return &cv; +} static int gThreadsStarted = 0; static int gThreadsInMiddle = 0; @@ -256,35 +262,35 @@ public: // This is the code that each of the spawned threads runs. // All threads move together throught the started - middle - done sequence together, // waiting for all other threads to reach each point before advancing. - umtx_lock(&gTestMutexA); + umtx_lock(gTestMutexA()); gThreadsStarted += 1; - umtx_condBroadcast(&gThreadsCountChanged); + umtx_condBroadcast(gThreadsCountChanged()); while (gThreadsStarted < TESTMUTEX_THREAD_COUNT) { if (gThreadsInMiddle != 0) { IntlTest::gTest->errln( "%s:%d gThreadsInMiddle = %d. Expected 0.", __FILE__, __LINE__, gThreadsInMiddle); return; } - umtx_condWait(&gThreadsCountChanged, &gTestMutexA); + umtx_condWait(gThreadsCountChanged(), gTestMutexA()); } gThreadsInMiddle += 1; - umtx_condBroadcast(&gThreadsCountChanged); + umtx_condBroadcast(gThreadsCountChanged()); while (gThreadsInMiddle < TESTMUTEX_THREAD_COUNT) { if (gThreadsDone != 0) { IntlTest::gTest->errln( "%s:%d gThreadsDone = %d. Expected 0.", __FILE__, __LINE__, gThreadsDone); return; } - umtx_condWait(&gThreadsCountChanged, &gTestMutexA); + umtx_condWait(gThreadsCountChanged(), gTestMutexA()); } gThreadsDone += 1; - umtx_condBroadcast(&gThreadsCountChanged); + umtx_condBroadcast(gThreadsCountChanged()); while (gThreadsDone < TESTMUTEX_THREAD_COUNT) { - umtx_condWait(&gThreadsCountChanged, &gTestMutexA); + umtx_condWait(gThreadsCountChanged(), gTestMutexA()); } - umtx_unlock(&gTestMutexA); + umtx_unlock(gTestMutexA()); } }; @@ -295,7 +301,7 @@ void MultithreadTest::TestMutex() gThreadsDone = 0; int32_t i = 0; TestMutexThread threads[TESTMUTEX_THREAD_COUNT]; - umtx_lock(&gTestMutexA); + umtx_lock(gTestMutexA()); for (i=0; ierrln("File %s, Line %d: Error, gStartedThreads = %d, gFinishedThreads = %d", __FILE__, __LINE__, gStartedThreads, gFinishedThreads); } - umtx_condWait(&gCTConditionVar, &gCTMutex); + umtx_condWait(gCTConditionVar(), gCTMutex()); } gFinishedThreads += gConditionTestOne; fFinished = true; - umtx_condBroadcast(&gCTConditionVar); + umtx_condBroadcast(gCTConditionVar()); while (gFinishedThreads < NUMTHREADS) { - umtx_condWait(&gCTConditionVar, &gCTMutex); + umtx_condWait(gCTConditionVar(), gCTMutex()); } - umtx_unlock(&gCTMutex); + umtx_unlock(gCTMutex()); } void MultithreadTest::TestConditionVariables() { @@ -1204,7 +1216,7 @@ void MultithreadTest::TestConditionVariables() { gFinishedThreads = 0; int i; - umtx_lock(&gCTMutex); + umtx_lock(gCTMutex()); CondThread *threads[NUMTHREADS]; for (i=0; ifFinished); @@ -1280,7 +1292,7 @@ const UCTMultiThreadItem *LocaleCacheKey::createObject( return result; } - umtx_lock(&gCTMutex); + umtx_lock(gCTMutex()); bool firstObject = (gObjectsCreated == 0); if (firstObject) { // Force the first object creation that comes through to wait @@ -1291,10 +1303,10 @@ const UCTMultiThreadItem *LocaleCacheKey::createObject( // early, to keep subsequent threads from entering this path. gObjectsCreated = 1; while (gObjectsCreated < 3) { - umtx_condWait(&gCTConditionVar, &gCTMutex); + umtx_condWait(gCTConditionVar(), gCTMutex()); } } - umtx_unlock(&gCTMutex); + umtx_unlock(gCTMutex()); const UCTMultiThreadItem *result = new UCTMultiThreadItem(fLoc.getLanguage()); @@ -1306,12 +1318,12 @@ const UCTMultiThreadItem *LocaleCacheKey::createObject( // Log that we created an object. The first object was already counted, // don't do it again. - umtx_lock(&gCTMutex); + umtx_lock(gCTMutex()); if (!firstObject) { gObjectsCreated += 1; } - umtx_condBroadcast(&gCTConditionVar); - umtx_unlock(&gCTMutex); + umtx_condBroadcast(gCTConditionVar()); + umtx_unlock(gCTMutex()); return result; } -- 2.50.1