]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/ucnv_bld.cpp
ICU-64232.0.1.tar.gz
[apple/icu.git] / icuSources / common / ucnv_bld.cpp
index 58335d1877e30dbb622e24634110d30f667caf05..42ddbd3aaa42c77179e3c4c8a41e6dfc056cb433 100644 (file)
@@ -1,7 +1,9 @@
+// © 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.
  ********************************************************************
  *
@@ -192,9 +194,12 @@ static struct {
 
 /*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;
@@ -259,6 +264,11 @@ static UBool U_CALLCONV ucnv_cleanup(void) {
     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*/,
@@ -292,6 +302,7 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo
 
     if( (uint16_t)type >= UCNV_NUMBER_OF_SUPPORTED_CONVERTER_TYPES ||
         converterData[type] == NULL ||
+        !converterData[type]->isReferenceCounted ||
         converterData[type]->referenceCounter != 1 ||
         source->structSize != sizeof(UConverterStaticData))
     {
@@ -308,26 +319,6 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo
     /* 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;
@@ -338,7 +329,6 @@ ucnv_data_unFlattenClone(UConverterLoadArgs *pArgs, UDataMemory *pData, UErrorCo
     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;
         }
@@ -405,7 +395,7 @@ getAlgorithmicTypeFromName(const char *realName)
 
     /* do a binary search for the alias */
     start = 0;
-    limit = sizeof(cnvNameType)/sizeof(cnvNameType[0]);
+    limit = UPRV_LENGTHOF(cnvNameType);
     mid = limit;
     lastMid = UINT32_MAX;
 
@@ -457,7 +447,7 @@ ucnv_shareConverterData(UConverterSharedData * data)
         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;
@@ -542,25 +532,6 @@ ucnv_deleteSharedConverterData(UConverterSharedData * deadSharedData)
         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);
@@ -611,7 +582,7 @@ ucnv_load(UConverterLoadArgs *pArgs, UErrorCode *err) {
 
 /**
  * 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
@@ -630,30 +601,20 @@ ucnv_unload(UConverterSharedData *sharedData) {
 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());
     }
 }
 
@@ -854,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;
@@ -940,12 +901,7 @@ ucnv_createAlgorithmicConverter(UConverter *myUConverter,
     }
 
     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);
@@ -1108,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
@@ -1137,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);
 
@@ -1151,7 +1107,7 @@ static void U_CALLCONV initAvailableConvertersList(UErrorCode &errCode) {
     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)) {
@@ -1243,7 +1199,7 @@ internalSetName(const char *name, UErrorCode *status) {
     }
     algorithmicSharedData = getAlgorithmicTypeFromName(stackArgs.name);
 
-    umtx_lock(&cnvCacheMutex);
+    umtx_lock(cnvCacheMutex());
 
     gDefaultAlgorithmicSharedData = algorithmicSharedData;
     gDefaultConverterContainsOption = containsOption;
@@ -1257,9 +1213,9 @@ internalSetName(const char *name, UErrorCode *status) {
     //             -- Andy
     gDefaultConverterName = gDefaultConverterNameBuffer;
 
-    ucln_common_registerCleanup(UCLN_COMMON_UCNV, ucnv_cleanup);
+    ucnv_enableCleanup();
 
-    umtx_unlock(&cnvCacheMutex);
+    umtx_unlock(cnvCacheMutex());
 }
 #endif
 
@@ -1284,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) {