+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
/*
********************************************************************
* COPYRIGHT:
- * Copyright (c) 1996-2015, International Business Machines Corporation and
+ * Copyright (c) 1996-2016, International Business Machines Corporation and
* others. All Rights Reserved.
********************************************************************
*
/*initializes some global variables */
static UHashtable *SHARED_DATA_HASHTABLE = NULL;
-static 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 = STATIC_NEW(icu::UMutex);
+ return m;
+}
+/* Note: the global mutex is used for */
+/* reference count updates. */
static const char **gAvailableConverters = NULL;
static uint16_t gAvailableConverterCount = 0;
return (SHARED_DATA_HASHTABLE == NULL);
}
+U_CAPI void U_EXPORT2
+ucnv_enableCleanup() {
+ ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
+}
+
static UBool U_CALLCONV
isCnvAcceptable(void * /*context*/,
const char * /*type*/, const char * /*name*/,
if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES ||
converterData[type] == NULL ||
+ !converterData[type]->isReferenceCounted ||
converterData[type]->referenceCounter != 1 ||
source->structSize != sizeof(UConverterStaticData))
{
/* copy initial values from the static structure for this type */
uprv_memcpy(data, converterData[type], sizeof(UConverterSharedData));
-#if 0 /* made UConverterMBCSTable part of UConverterSharedData -- markus 20031107 */
- /*
- * It would be much more efficient if the table were a direct member, not a pointer.
- * However, that would add to the size of all UConverterSharedData objects
- * even if they do not use this table (especially algorithmic ones).
- * If this changes, then the static templates from converterData[type]
- * need more entries.
- *
- * In principle, it would be cleaner if the load() function below
- * allocated the table.
- */
- data->table = (UConverterTable *)uprv_malloc(sizeof(UConverterTable));
- if(data->table == NULL) {
- uprv_free(data);
- *status = U_MEMORY_ALLOCATION_ERROR;
- return NULL;
- }
- uprv_memset(data->table, 0, sizeof(UConverterTable));
-#endif
-
data->staticData = source;
data->sharedDataCached = FALSE;
if(data->impl->load != NULL) {
data->impl->load(data, pArgs, raw + source->structSize, status);
if(U_FAILURE(*status)) {
- uprv_free(data->table);
uprv_free(data);
return NULL;
}
/* do a binary search for the alias */
start = 0;
- limit = sizeof(cnvNameType)/sizeof(cnvNameType[0]);
+ limit = UPRV_LENGTHOF(cnvNameType);
mid = limit;
lastMid = UINT32_MAX;
SHARED_DATA_HASHTABLE = uhash_openSize(uhash_hashChars, uhash_compareChars, NULL,
ucnv_io_countKnownConverters(&err)*UCNV_CACHE_LOAD_FACTOR,
&err);
- ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
+ ucnv_enableCleanup();
if (U_FAILURE(err))
return;
udata_close(data);
}
- if(deadSharedData->table != NULL)
- {
- uprv_free(deadSharedData->table);
- }
-
-#if 0
- /* if the static data is actually owned by the shared data */
- /* enable if we ever have this situation. */
- if(deadSharedData->staticDataOwned == TRUE) /* see ucnv_bld.h */
- {
- uprv_free((void*)deadSharedData->staticData);
- }
-#endif
-
-#if 0
- /* Zap it ! */
- uprv_memset(deadSharedData->0, sizeof(*deadSharedData));
-#endif
-
uprv_free(deadSharedData);
UTRACE_EXIT_VALUE((int32_t)TRUE);
/**
* Unload a non-algorithmic converter.
- * It must be sharedData->referenceCounter != ~0
+ * It must be sharedData->isReferenceCounted
* and this function must be called inside umtx_lock(&cnvCacheMutex).
*/
U_CAPI void
U_CFUNC void
ucnv_unloadSharedDataIfReady(UConverterSharedData *sharedData)
{
- /*
- Checking whether it's an algorithic converter is okay
- in multithreaded applications because the value never changes.
- Don't check referenceCounter for any other value.
- */
- if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
- umtx_lock(&cnvCacheMutex);
+ if(sharedData != NULL && sharedData->isReferenceCounted) {
+ umtx_lock(cnvCacheMutex());
ucnv_unload(sharedData);
- umtx_unlock(&cnvCacheMutex);
+ umtx_unlock(cnvCacheMutex());
}
}
U_CFUNC void
ucnv_incrementRefCount(UConverterSharedData *sharedData)
{
- /*
- Checking whether it's an algorithic converter is okay
- in multithreaded applications because the value never changes.
- Don't check referenceCounter for any other value.
- */
- if(sharedData != NULL && sharedData->referenceCounter != (uint32_t)~0) {
- umtx_lock(&cnvCacheMutex);
+ if(sharedData != NULL && sharedData->isReferenceCounted) {
+ umtx_lock(cnvCacheMutex());
sharedData->referenceCounter++;
- umtx_unlock(&cnvCacheMutex);
+ umtx_unlock(cnvCacheMutex());
}
}
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;
}
sharedData = converterData[type];
- /*
- Checking whether it's an algorithic converter is okay
- in multithreaded applications because the value never changes.
- Don't check referenceCounter for any other value.
- */
- if(sharedData == NULL || sharedData->referenceCounter != (uint32_t)~0) {
+ if(sharedData == NULL || sharedData->isReferenceCounted) {
/* not a valid type, or not an algorithmic converter */
*err = U_ILLEGAL_ARGUMENT_ERROR;
UTRACE_EXIT_STATUS(U_ILLEGAL_ARGUMENT_ERROR);
* 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
}
}
} while(++i == 1 && remaining > 0);
- umtx_unlock(&cnvCacheMutex);
+ umtx_unlock(cnvCacheMutex());
UTRACE_DATA1(UTRACE_INFO, "ucnv_flushCache() exits with %d converters remaining", remaining);
U_ASSERT(gAvailableConverterCount == 0);
U_ASSERT(gAvailableConverters == NULL);
- ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
+ ucnv_enableCleanup();
UEnumeration *allConvEnum = ucnv_openAllNames(&errCode);
int32_t allConverterCount = uenum_count(allConvEnum, &errCode);
if (U_FAILURE(errCode)) {
}
algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
- umtx_lock(&cnvCacheMutex);
+ umtx_lock(cnvCacheMutex());
gDefaultAlgorithmicSharedData = algorithmicSharedData;
gDefaultConverterContainsOption = containsOption;
// -- Andy
gDefaultConverterName = gDefaultConverterNameBuffer;
- ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
+ ucnv_enableCleanup();
- umtx_unlock(&cnvCacheMutex);
+ umtx_unlock(cnvCacheMutex());
}
#endif
but ucnv_setDefaultName is not thread safe.
*/
{
- icu::Mutex lock(&cnvCacheMutex);
+ icu::Mutex lock(cnvCacheMutex());
name = gDefaultConverterName;
}
if(name==NULL) {