TitlecaseTransliterator::TitlecaseTransliterator(const Locale& theLoc) : Transliterator(_ID, 0), loc(theLoc), buffer(0) { buffer = (UChar *)uprv_malloc(u_getMaxCaseExpansion()*sizeof(buffer[0])); // Need to look back 2 characters in the case of "can't" setMaximumContextLength(2); umtx_lock(NULL); UBool f = (SKIP == NULL); umtx_unlock(NULL); if (f) { UErrorCode ec = U_ZERO_ERROR; UnicodeSet* skip = new UnicodeSet(UNICODE_STRING_SIMPLE("[\\u00AD \\u2019 \\' [:Mn:] [:Me:] [:Cf:] [:Lm:] [:Sk:]]"), ec); UnicodeSet* cased = new UnicodeSet(UNICODE_STRING_SIMPLE("[[:Lu:] [:Ll:] [:Lt:]]"), ec); if (skip != NULL && cased != NULL && U_SUCCESS(ec)) { umtx_lock(NULL); if (SKIP == NULL) { SKIP = skip; CASED = cased; skip = cased = NULL; } umtx_unlock(NULL); } delete skip; delete cased; ucln_i18n_registerCleanup(); } }
U_CAPI void U_EXPORT2 umtx_condWait(UConditionVar *condition, UMutex *mutex) { if (condition->fEntryGate == NULL) { // Note: because the associated mutex must be locked when calling // wait, we know that there can not be multiple threads // running here with the same condition variable. // Meaning that lazy initialization is safe. U_ASSERT(condition->fExitGate == NULL); condition->fEntryGate = CreateEvent(NULL, // Security Attributes TRUE, // Manual Reset FALSE, // Initially reset NULL); // Name. U_ASSERT(condition->fEntryGate != NULL); condition->fExitGate = CreateEvent(NULL, TRUE, TRUE, NULL); U_ASSERT(condition->fExitGate != NULL); } condition->fWaitCount++; umtx_unlock(mutex); WaitForSingleObject(condition->fEntryGate, INFINITE); umtx_lock(mutex); condition->fWaitCount--; if (condition->fWaitCount == 0) { // All threads that were waiting at the entry gate have woken up // and moved through. Shut the entry gate and open the exit gate. ResetEvent(condition->fEntryGate); SetEvent(condition->fExitGate); } else { umtx_unlock(mutex); WaitForSingleObject(condition->fExitGate, INFINITE); umtx_lock(mutex); } }
CollData *CollDataCache::get(UCollator *collator, UErrorCode &status) { char keyBuffer[KEY_BUFFER_SIZE]; int32_t keyLength = KEY_BUFFER_SIZE; char *key = getKey(collator, keyBuffer, &keyLength); CollData *result = NULL, *newData = NULL; CollDataCacheEntry *entry = NULL, *newEntry = NULL; umtx_lock(&lock); entry = (CollDataCacheEntry *) uhash_get(cache, key); if (entry == NULL) { umtx_unlock(&lock); newData = new CollData(collator, key, keyLength, status); newEntry = new CollDataCacheEntry(newData); if (U_FAILURE(status) || newData == NULL || newEntry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } umtx_lock(&lock); entry = (CollDataCacheEntry *) uhash_get(cache, key); if (entry == NULL) { uhash_put(cache, newData->key, newEntry, &status); umtx_unlock(&lock); if (U_FAILURE(status)) { delete newEntry; delete newData; return NULL; } return newData; } } result = entry->data; entry->refCount += 1; umtx_unlock(&lock); if (key != keyBuffer) { deleteKey(key); } if (newEntry != NULL) { delete newEntry; delete newData; } return result; }
U_CAPI void U_EXPORT2 umtx_init(UMTX *mutex) { #if (ICU_USE_THREADS == 1) if (mutex == NULL) /* initialize the global mutex */ { /* Note: The initialization of the global mutex is NOT thread safe. */ if (gGlobalMutex != NULL) { return; } gGlobalMutex = umtx_raw_init(&gPlatformMutex); # ifdef POSIX_DEBUG_REENTRANCY gInMutex = FALSE; # endif #ifdef _DEBUG gRecursionCount = 0; #endif #ifdef POSIX umtx_raw_init(&gIncDecMutex); #endif } else { /* Not the global mutex. * Thread safe initialization, using the global mutex. */ UBool isInitialized; UMTX tMutex = NULL; umtx_lock(NULL); isInitialized = (*mutex != NULL); umtx_unlock(NULL); if (isInitialized) { return; } tMutex = umtx_raw_init(NULL); umtx_lock(NULL); if (*mutex == NULL) { *mutex = tMutex; tMutex = NULL; } umtx_unlock(NULL); umtx_destroy(&tMutex); /* NOP if (tmutex == NULL) */ } #endif /* ICU_USE_THREADS==1 */ }
virtual void run() { // This is the code that each of the spawned threads runs. // All of the spawned threads bunch up together at each of the two mutexes // because the main holds the mutexes until they do. // safeIncr(gThreadsStarted, 1); umtx_lock(&gTestMutexA); umtx_unlock(&gTestMutexA); safeIncr(gThreadsInMiddle, 1); umtx_lock(&gTestMutexB); umtx_unlock(&gTestMutexB); safeIncr(gThreadsDone, 1); }
template<> U_EXPORT const UCTMultiThreadItem *LocaleCacheKey<UCTMultiThreadItem>::createObject( const void *context, UErrorCode &status) const { const UnifiedCache *cacheContext = (const UnifiedCache *) context; if (uprv_strcmp(fLoc.getLanguage(), fLoc.getName()) != 0) { const UCTMultiThreadItem *result = NULL; if (cacheContext == NULL) { UnifiedCache::getByLocale(fLoc.getLanguage(), result, status); return result; } cacheContext->get(LocaleCacheKey<UCTMultiThreadItem>(fLoc.getLanguage()), result, status); return result; } umtx_lock(&gCTMutex); bool firstObject = (gObjectsCreated == 0); if (firstObject) { // Force the first object creation that comes through to wait // until other have completed. Verifies that cache doesn't // deadlock when a creation is slow. // Note that gObjectsCreated needs to be incremeneted from 0 to 1 // early, to keep subsequent threads from entering this path. gObjectsCreated = 1; while (gObjectsCreated < 3) { umtx_condWait(&gCTConditionVar, &gCTMutex); } } umtx_unlock(&gCTMutex); const UCTMultiThreadItem *result = new UCTMultiThreadItem(fLoc.getLanguage()); if (result == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { result->addRef(); } // Log that we created an object. The first object was already counted, // don't do it again. umtx_lock(&gCTMutex); if (!firstObject) { gObjectsCreated += 1; } umtx_condBroadcast(&gCTConditionVar); umtx_unlock(&gCTMutex); return result; }
const char* TimeZone::getTZDataVersion(UErrorCode& status) { /* This is here to prevent race conditions. */ UBool needsInit; UMTX_CHECK(&LOCK, !TZDataVersionInitialized, needsInit); if (needsInit) { int32_t len = 0; UResourceBundle *bundle = ures_openDirect(NULL, "zoneinfo", &status); const UChar *tzver = ures_getStringByKey(bundle, "TZVersion", &len, &status); if (U_SUCCESS(status)) { if (len >= (int32_t)sizeof(TZDATA_VERSION)) { // Ensure that there is always space for a trailing nul in TZDATA_VERSION len = sizeof(TZDATA_VERSION) - 1; } umtx_lock(&LOCK); if (!TZDataVersionInitialized) { u_UCharsToChars(tzver, TZDATA_VERSION, len); TZDataVersionInitialized = TRUE; } umtx_unlock(&LOCK); ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup); } ures_close(bundle); } if (U_FAILURE(status)) { return NULL; } return (const char*)TZDATA_VERSION; }
double IslamicCalendar::moonAge(UDate time, UErrorCode &status) { double age = 0; umtx_lock(&astroLock); if(gIslamicCalendarAstro == NULL) { gIslamicCalendarAstro = new CalendarAstronomer(); if (gIslamicCalendarAstro == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return age; } ucln_i18n_registerCleanup(UCLN_I18N_ISLAMIC_CALENDAR, calendar_islamic_cleanup); } gIslamicCalendarAstro->setTime(time); age = gIslamicCalendarAstro->getMoonAge(); umtx_unlock(&astroLock); // Convert to degrees and normalize... age = age * 180 / CalendarAstronomer::PI; if (age > 180) { age = age - 360; } return age; }
static void setCommonICUData(UDataMemory *pData, /* The new common data. Belongs to caller, we copy it. */ UDataMemory *oldData, /* Old ICUData ptr. Overwrite of this value is ok, */ /* of any others is not. */ UBool warn, /* If true, set USING_DEFAULT warning if ICUData was */ /* changed by another thread before we got to it. */ UErrorCode *pErr) { UDataMemory *newCommonData = UDataMemory_createNewInstance(pErr); if (U_FAILURE(*pErr)) { return; } /* For the assignment, other threads must cleanly see either the old */ /* or the new, not some partially initialized new. The old can not be */ /* deleted - someone may still have a pointer to it lying around in */ /* their locals. */ UDatamemory_assign(newCommonData, pData); umtx_lock(NULL); if (gCommonICUData==oldData) { gStubICUData = gCommonICUData; /* remember the old Common Data, so it can be cleaned up. */ gCommonICUData = newCommonData; ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup); } else { if (warn==TRUE) { *pErr = U_USING_DEFAULT_WARNING; } uprv_free(newCommonData); } umtx_unlock(NULL); }
/* udata_getCacheHashTable() * Get the hash table used to store the data cache entries. * Lazy create it if it doesn't yet exist. */ static UHashtable *udata_getHashTable() { UErrorCode err = U_ZERO_ERROR; UBool cacheIsInitialized; UHashtable *tHT = NULL; UMTX_CHECK(NULL, (gCommonDataCache != NULL), cacheIsInitialized); if (cacheIsInitialized) { return gCommonDataCache; } tHT = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &err); /* Check for null pointer. */ if (tHT == NULL) { return NULL; /* TODO: Handle this error better. */ } uhash_setValueDeleter(tHT, DataCacheElement_deleter); umtx_lock(NULL); if (gCommonDataCache == NULL) { gCommonDataCache = tHT; tHT = NULL; ucln_common_registerCleanup(UCLN_COMMON_UDATA, udata_cleanup); } umtx_unlock(NULL); if (tHT != NULL) { uhash_close(tHT); } if (U_FAILURE(err)) { return NULL; /* TODO: handle this error better. */ } return gCommonDataCache; }
/** * Inline function that returns TRUE if we have zone data, loading it * if necessary. The only time this function will return false is if * loadZoneData() fails, and UDATA_MEMORY and associated pointers are * NULL (rare). * * The difference between this function and loadZoneData() is that * this is an inline function that expands to code which avoids making * a function call in the case where the data is already loaded (the * common case). * * Must be called OUTSIDE mutex. */ static inline UBool haveZoneData() { umtx_init(&LOCK); /* This is here to prevent race conditions. */ umtx_lock(&LOCK); UBool f = (UDATA_MEMORY != 0); umtx_unlock(&LOCK); return f || loadZoneData(); }
/** * Return the major solar term on or after December 15 of the given * Gregorian year, that is, the winter solstice of the given year. * Computations are relative to Asia/Shanghai time zone. * @param gyear a Gregorian year * @return days after January 1, 1970 0:00 Asia/Shanghai of the * winter solstice of the given year */ int32_t ChineseCalendar::winterSolstice(int32_t gyear) const { UErrorCode status = U_ZERO_ERROR; int32_t cacheValue = CalendarCache::get(&gChineseCalendarWinterSolsticeCache, gyear, status); if (cacheValue == 0) { // In books December 15 is used, but it fails for some years // using our algorithms, e.g.: 1298 1391 1492 1553 1560. That // is, winterSolstice(1298) starts search at Dec 14 08:00:00 // 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); 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); // Winter solstice is 270 degrees solar longitude aka Dongzhi cacheValue = (int32_t)millisToDays(solarLong); CalendarCache::put(&gChineseCalendarWinterSolsticeCache, gyear, cacheValue, status); } if(U_FAILURE(status)) { cacheValue = 0; } return cacheValue; }
/* * ICU Initialization Function. Need not be called. */ U_CAPI void U_EXPORT2 u_init(UErrorCode *status) { UTRACE_ENTRY_OC(UTRACE_U_INIT); /* initialize plugins */ uplug_init(status); umtx_lock(&gICUInitMutex); if (gICUInitialized || U_FAILURE(*status)) { umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); return; } /* * 2005-may-02 * * ICU4C 3.4 (jitterbug 4497) hardcodes the data for Unicode character * properties for APIs that want to be fast. * Therefore, we need not load them here nor check for errors. * Instead, we load the converter alias table to see if any ICU data * is available. * Users should really open the service objects they need and check * for errors there, to make sure that the actual items they need are * available. */ #if !UCONFIG_NO_CONVERSION ucnv_io_countKnownConverters(status); #endif gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */ umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); }
UConverter * ucnv_createAlgorithmicConverter(UConverter *myUConverter, UConverterType type, const char *locale, uint32_t options, UErrorCode *err) { UConverter *cnv; const UConverterSharedData *sharedData; UBool isAlgorithmicConverter; UTRACE_ENTRY_OC(UTRACE_UCNV_OPEN_ALGORITHMIC); UTRACE_DATA1(UTRACE_OPEN_CLOSE, "open algorithmic converter type %d", (int32_t)type); if(type<0 || UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES<=type) { *err = U_ILLEGAL_ARGUMENT_ERROR; UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR); return NULL; } sharedData = converterData[type]; umtx_lock(&cnvCacheMutex); isAlgorithmicConverter = (UBool)(sharedData == NULL || sharedData->referenceCounter != ~0); umtx_unlock(&cnvCacheMutex); if (isAlgorithmicConverter) { /* not a valid type, or not an algorithmic converter */ *err = U_ILLEGAL_ARGUMENT_ERROR; UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR); return NULL; } cnv = ucnv_createConverterFromSharedData(myUConverter, (UConverterSharedData *)sharedData, "", locale != NULL ? locale : "", options, err); UTRACE_EXIT_PTR_STATUS(cnv, *err); return cnv; }
U_CAPI void U_EXPORT2 u_init(UErrorCode *status) { UTRACE_ENTRY_OC(UTRACE_U_INIT); /* Make sure the global mutexes are initialized. */ umtx_init(NULL); umtx_lock(&gICUInitMutex); if (gICUInitialized || U_FAILURE(*status)) { umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); return; } /* Do any required init for services that don't have open operations * and use "only" the double-check initialization method for performance * reasons (avoiding a mutex lock even for _checking_ whether the * initialization had occurred). */ /* Char Properties */ uprv_loadPropsData(status); #if !UCONFIG_NO_NORMALIZATION /* Normalization */ unorm_haveData(status); #endif gICUInitialized = TRUE; /* TODO: don't set if U_FAILURE? */ umtx_unlock(&gICUInitMutex); UTRACE_EXIT_STATUS(*status); }
void IslamicCalendar::initializeSystemDefaultCentury() { // initialize systemDefaultCentury and systemDefaultCenturyYear based // on the current time. They'll be set to 80 years before // the current time. // No point in locking as it should be idempotent. if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) { UErrorCode status = U_ZERO_ERROR; IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status); if (U_SUCCESS(status)) { calendar.setTime(Calendar::getNow(), status); calendar.add(UCAL_YEAR, -80, status); UDate newStart = calendar.getTime(status); int32_t newYear = calendar.get(UCAL_YEAR, status); { umtx_lock(NULL); fgSystemDefaultCenturyStart = newStart; fgSystemDefaultCenturyStartYear = newYear; umtx_unlock(NULL); } } // We have no recourse upon failure unless we want to propagate the failure // out. } }
static void removeLastUStringFromTable(void) { umtx_lock(&gZoneMetaLock); if (gUStringCount > 0) { free(gUStringTable[--gUStringCount]); } umtx_unlock(&gZoneMetaLock); }
/* * Set the data directory. * Make a copy of the passed string, and set the global data dir to point to it. * TODO: see bug #2849, regarding thread safety. */ U_CAPI void U_EXPORT2 u_setDataDirectory(const char *directory) { char *newDataDir; int32_t length; if(directory==NULL || *directory==0) { /* A small optimization to prevent the malloc and copy when the shared library is used, and this is a way to make sure that NULL is never returned. */ newDataDir = (char *)""; } else { length=(int32_t)uprv_strlen(directory); newDataDir = (char *)uprv_malloc(length + 2); uprv_strcpy(newDataDir, directory); #if (U_FILE_SEP_CHAR != U_FILE_ALT_SEP_CHAR) { char *p; while(p = uprv_strchr(newDataDir, U_FILE_ALT_SEP_CHAR)) { *p = U_FILE_SEP_CHAR; } } #endif } umtx_lock(NULL); if (gDataDirectory && *gDataDirectory) { uprv_free(gDataDirectory); } gDataDirectory = newDataDir; ucln_common_registerCleanup(UCLN_COMMON_PUTIL, putil_cleanup); umtx_unlock(NULL); }
virtual void run() { // 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); gThreadsStarted += 1; 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); } gThreadsInMiddle += 1; 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); } gThreadsDone += 1; umtx_condBroadcast(&gThreadsCountChanged); while (gThreadsDone < TESTMUTEX_THREAD_COUNT) { umtx_condWait(&gThreadsCountChanged, &gTestMutexA); } umtx_unlock(&gTestMutexA); }
/** * Initialize static memory. */ void TransliteratorIDParser::init(UErrorCode & status) { if (SPECIAL_INVERSES != NULL) { return; } Hashtable * special_inverses = new Hashtable(TRUE, status); // Null pointer check if (special_inverses == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return; } special_inverses->setValueDeleter(uhash_deleteUnicodeString); umtx_lock(&LOCK); if (SPECIAL_INVERSES == NULL) { SPECIAL_INVERSES = special_inverses; special_inverses = NULL; } umtx_unlock(&LOCK); delete special_inverses; /*null instance*/ ucln_i18n_registerCleanup(UCLN_I18N_TRANSLITERATOR, utrans_transliterator_cleanup); }
U_COMMON_API int32_t U_EXPORT2 umtx_loadAcquire(u_atomic_int32_t &var) { umtx_lock(&gIncDecMutex); int32_t val = var; umtx_unlock(&gIncDecMutex); return val; }
U_CDECL_END /** * Load the property names data. Caller should check that data is * not loaded BEFORE calling this function. Returns TRUE if the load * succeeds. */ static UBool _load() { UErrorCode ec = U_ZERO_ERROR; UDataMemory* data = udata_openChoice(0, PNAME_DATA_TYPE, PNAME_DATA_NAME, isPNameAcceptable, 0, &ec); if (U_SUCCESS(ec)) { umtx_lock(NULL); if (UDATA == NULL) { UDATA = data; PNAME = (const PropertyAliases*) udata_getMemory(UDATA); ucln_common_registerCleanup(UCLN_COMMON_PNAME, pname_cleanup); data = NULL; } umtx_unlock(NULL); } if (data) { udata_close(data); } return PNAME!=NULL; }
void EthiopicCalendar::initializeSystemDefaultCentury() { // lazy-evaluate systemDefaultCenturyStart UBool needsUpdate; UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate); if (!needsUpdate) { return; } UErrorCode status = U_ZERO_ERROR; EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status); if (U_SUCCESS(status)) { calendar.setTime(Calendar::getNow(), status); calendar.add(UCAL_YEAR, -80, status); UDate newStart = calendar.getTime(status); int32_t newYear = calendar.get(UCAL_YEAR, status); { umtx_lock(NULL); fgSystemDefaultCenturyStartYear = newYear; fgSystemDefaultCenturyStart = newStart; umtx_unlock(NULL); } } // We have no recourse upon failure unless we want to propagate the failure // out. }
/* get the UBiDiProps singleton, or else its dummy, once and for all */ static const UBiDiProps * getBiDiProps() { /* * This lazy intialization with double-checked locking (without mutex protection for * the initial check) is transiently unsafe under certain circumstances. * Check the readme and use u_init() if necessary. */ /* the initial check is performed by the GET_BIDI_PROPS() macro */ const UBiDiProps *bdp; UErrorCode errorCode=U_ZERO_ERROR; bdp=ubidi_getSingleton(&errorCode); #if !UBIDI_HARDCODE_DATA if(U_FAILURE(errorCode)) { errorCode=U_ZERO_ERROR; bdp=ubidi_getDummy(&errorCode); if(U_FAILURE(errorCode)) { return NULL; } } #endif umtx_lock(NULL); if(gBdp==NULL) { gBdp=bdp; ucln_common_registerCleanup(UCLN_COMMON_UPROPS, uprops_cleanup); } umtx_unlock(NULL); return gBdp; }
void TaiwanCalendar::initializeSystemDefaultCentury() { // initialize systemDefaultCentury and systemDefaultCenturyYear based // on the current time. They'll be set to 80 years before // the current time. UErrorCode status = U_ZERO_ERROR; TaiwanCalendar calendar(Locale("@calendar=roc"),status); if (U_SUCCESS(status)) { calendar.setTime(Calendar::getNow(), status); calendar.add(UCAL_YEAR, -80, status); UDate newStart = calendar.getTime(status); int32_t newYear = calendar.get(UCAL_YEAR, status); umtx_lock(NULL); if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) { fgSystemDefaultCenturyStartYear = newYear; fgSystemDefaultCenturyStart = newStart; } umtx_unlock(NULL); } // We have no recourse upon failure unless we want to propagate the failure // out. }
U_CAPI int32_t U_EXPORT2 umtx_atomic_dec(int32_t *p) { int32_t retVal; if (pDecFn) { retVal = (*pDecFn)(gIncDecContext, p); } else { #if !ICU_USE_THREADS /* ICU thread support compiled out. */ retVal = --(*p); #elif 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; }
CollDataCache::~CollDataCache() { umtx_lock(&lock); uhash_close(cache); cache = NULL; umtx_unlock(&lock); }
U_CDECL_END void SimpleDateFormatStaticSets::initSets(UErrorCode *status) { SimpleDateFormatStaticSets *p; UMTX_CHECK(NULL, gStaticSets, p); if (p == NULL) { p = new SimpleDateFormatStaticSets(status); if (p == NULL) { *status = U_MEMORY_ALLOCATION_ERROR; return; } if (U_FAILURE(*status)) { delete p; return; } umtx_lock(NULL); if (gStaticSets == NULL) { gStaticSets = p; p = NULL; } umtx_unlock(NULL); if (p != NULL) { delete p; } ucln_i18n_registerCleanup(UCLN_I18N_SMPDTFMT, smpdtfmt_cleanup); } }
U_CAPI UConverter* U_EXPORT2 u_getDefaultConverter(UErrorCode *status) { UConverter *converter = NULL; if (gDefaultConverter != NULL) { umtx_lock(NULL); /* need to check to make sure it wasn't taken out from under us */ if (gDefaultConverter != NULL) { converter = gDefaultConverter; gDefaultConverter = NULL; } umtx_unlock(NULL); } /* if the cache was empty, create a converter */ if(converter == NULL) { converter = ucnv_open(NULL, status); if(U_FAILURE(*status)) { ucnv_close(converter); converter = NULL; } } return converter; }
void MultithreadTest::TestConditionVariables() { gStartedThreads = 0; gFinishedThreads = 0; int i; umtx_lock(&gCTMutex); CondThread *threads[NUMTHREADS]; for (i=0; i<NUMTHREADS; ++i) { threads[i] = new CondThread; threads[i]->start(); } while (gStartedThreads < NUMTHREADS) { umtx_condWait(&gCTConditionVar, &gCTMutex); } while (gFinishedThreads < NUMTHREADS) { umtx_condWait(&gCTConditionVar, &gCTMutex); } umtx_unlock(&gCTMutex); for (i=0; i<NUMTHREADS; ++i) { if (!threads[i]->fFinished) { errln("File %s, Line %d: Error, threads[%d]->fFinished == false", __FILE__, __LINE__, i); } } for (i=0; i<NUMTHREADS; ++i) { threads[i]->join(); delete threads[i]; } }