blob: f246f157938ed37dd8381f3b7df346e52a977e55 [file] [log] [blame]
diff --git a/source/common/udata.cpp b/source/common/udata.cpp
index e6d8a35..80bea06 100644
--- a/source/common/udata.cpp
+++ b/source/common/udata.cpp
@@ -1,7 +1,7 @@
/*
******************************************************************************
*
-* Copyright (C) 1999-2014, International Business Machines
+* Copyright (C) 1999-2015, International Business Machines
* Corporation and others. All Rights Reserved.
*
******************************************************************************
@@ -29,6 +29,7 @@ might have to #include some other header
#include "charstr.h"
#include "cmemory.h"
#include "cstring.h"
+#include "mutex.h"
#include "putilimp.h"
#include "uassert.h"
#include "ucln_cmn.h"
@@ -100,14 +101,15 @@ static UDataMemory *udata_findCachedData(const char *path);
* that they really need, reducing the size of binaries that take advantage
* of this.
*/
-static UDataMemory *gCommonICUDataArray[10] = { NULL };
+static UDataMemory *gCommonICUDataArray[10] = { NULL }; // Access protected by icu global mutex.
-static UBool gHaveTriedToLoadCommonData = FALSE; /* See extendICUData(). */
+static u_atomic_int32_t gHaveTriedToLoadCommonData = ATOMIC_INT32_T_INITIALIZER(0); // See extendICUData().
static UHashtable *gCommonDataCache = NULL; /* Global hash table of opened ICU data files. */
static icu::UInitOnce gCommonDataCacheInitOnce = U_INITONCE_INITIALIZER;
-static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS;
+static UDataFileAccess gDataFileAccess = UDATA_DEFAULT_ACCESS; // Access not synchronized.
+ // Modifying is documented as thread-unsafe.
static UBool U_CALLCONV
udata_cleanup(void)
@@ -124,7 +126,7 @@ udata_cleanup(void)
udata_close(gCommonICUDataArray[i]);
gCommonICUDataArray[i] = NULL;
}
- gHaveTriedToLoadCommonData = FALSE;
+ gHaveTriedToLoadCommonData = 0;
return TRUE; /* Everything was cleaned up */
}
@@ -139,14 +141,16 @@ findCommonICUDataByName(const char *inBasename)
if (pData == NULL)
return FALSE;
- for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) {
- if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHeader == pData->pHeader)) {
- /* The data pointer is already in the array. */
- found = TRUE;
- break;
+ {
+ Mutex lock;
+ for (i = 0; i < UPRV_LENGTHOF(gCommonICUDataArray); ++i) {
+ if ((gCommonICUDataArray[i] != NULL) && (gCommonICUDataArray[i]->pHeader == pData->pHeader)) {
+ /* The data pointer is already in the array. */
+ found = TRUE;
+ break;
+ }
}
}
-
return found;
}
@@ -663,7 +667,11 @@ openCommonData(const char *path, /* Path from OpenChoice? */
if(commonDataIndex >= UPRV_LENGTHOF(gCommonICUDataArray)) {
return NULL;
}
- if(gCommonICUDataArray[commonDataIndex] == NULL) {
+ {
+ Mutex lock;
+ if(gCommonICUDataArray[commonDataIndex] != NULL) {
+ return gCommonICUDataArray[commonDataIndex];
+ }
int32_t i;
for(i = 0; i < commonDataIndex; ++i) {
if(gCommonICUDataArray[i]->pHeader == &U_ICUDATA_ENTRY_POINT.hdr) {
@@ -671,23 +679,26 @@ openCommonData(const char *path, /* Path from OpenChoice? */
return NULL;
}
}
+ }
- /* Add the linked-in data to the list. */
- /*
- * This is where we would check and call weakly linked partial-data-library
- * access functions.
- */
- /*
- if (uprv_getICUData_collation) {
- setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErrorCode);
- }
- if (uprv_getICUData_conversion) {
- setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode);
- }
- */
- setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT.hdr, FALSE, pErrorCode);
+ /* Add the linked-in data to the list. */
+ /*
+ * This is where we would check and call weakly linked partial-data-library
+ * access functions.
+ */
+ /*
+ if (uprv_getICUData_collation) {
+ setCommonICUDataPointer(uprv_getICUData_collation(), FALSE, pErrorCode);
+ }
+ if (uprv_getICUData_conversion) {
+ setCommonICUDataPointer(uprv_getICUData_conversion(), FALSE, pErrorCode);
+ }
+ */
+ setCommonICUDataPointer(&U_ICUDATA_ENTRY_POINT.hdr, FALSE, pErrorCode);
+ {
+ Mutex lock;
+ return gCommonICUDataArray[commonDataIndex];
}
- return gCommonICUDataArray[commonDataIndex];
}
@@ -795,7 +806,7 @@ static UBool extendICUData(UErrorCode *pErr)
static UMutex extendICUDataMutex = U_MUTEX_INITIALIZER;
umtx_lock(&extendICUDataMutex);
#endif
- if(!gHaveTriedToLoadCommonData) {
+ if(!umtx_loadAcquire(gHaveTriedToLoadCommonData)) {
/* See if we can explicitly open a .dat file for the ICUData. */
pData = openCommonData(
U_ICUDATA_NAME, /* "icudt20l" , for example. */
@@ -820,7 +831,7 @@ static UBool extendICUData(UErrorCode *pErr)
pErr); /* setCommonICUData honors errors; NOP if error set */
}
- gHaveTriedToLoadCommonData = TRUE;
+ umtx_storeRelease(gHaveTriedToLoadCommonData, 1);
}
didUpdate = findCommonICUDataByName(U_ICUDATA_NAME); /* Return 'true' when a racing writes out the extended */
@@ -1398,5 +1409,6 @@ udata_getInfo(UDataMemory *pData, UDataInfo *pInfo) {
U_CAPI void U_EXPORT2 udata_setFileAccess(UDataFileAccess access, UErrorCode * /*status*/)
{
+ // Note: this function is documented as not thread safe.
gDataFileAccess = access;
}