Index: source/common/udata.cpp |
diff --git a/source/common/udata.cpp b/source/common/udata.cpp |
index e6d8a3550d8ad9620498ea5ad0750a6fcc9acc96..80bea0631ef7dc21b69a4a3dc61fa6b5b5b5edcf 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; |
} |