ICU-6488 mutex cleanup in timezone code

X-SVN-Rev: 24452
This commit is contained in:
Andy Heninger 2008-08-06 21:01:19 +00:00
parent 1de383df48
commit d13d3b6d4d
2 changed files with 28 additions and 55 deletions

View File

@ -107,6 +107,7 @@ static U_NAMESPACE_QUALIFIER TimeZone* DEFAULT_ZONE = NULL;
static U_NAMESPACE_QUALIFIER TimeZone* _GMT = NULL; // cf. TimeZone::GMT
static char TZDATA_VERSION[16];
static UBool TZDataVersionInitialized = FALSE;
#ifdef U_USE_TIMEZONE_OBSOLETE_2_8
static U_NAMESPACE_QUALIFIER UnicodeString* OLSON_IDS = 0;
@ -127,6 +128,7 @@ static UBool U_CALLCONV timeZone_cleanup(void)
_GMT = NULL;
uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
TZDataVersionInitialized = FALSE;
if (LOCK) {
umtx_destroy(&LOCK);
@ -383,12 +385,15 @@ TimeZone::getGMT(void)
// Initialize _GMT independently of other static data; it should
// be valid even if we can't load the time zone UDataMemory.
if (needsInit) {
SimpleTimeZone *tmpGMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
umtx_lock(&LOCK);
if (_GMT == 0) {
_GMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
_GMT = tmpGMT;
tmpGMT = NULL;
}
umtx_unlock(&LOCK);
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
delete tmpGMT;
}
return _GMT;
}
@ -576,46 +581,6 @@ TimeZone::initDefault()
default_zone = NULL;
}
#if 0
// NOTE: As of ICU 2.8, we no longer have an offsets table, since
// historical zones can change offset over time. If we add
// build-time heuristics to infer the "most frequent" raw offset
// of a zone, we can build tables and institute defaults, as done
// in ICU <= 2.6.
// If we couldn't get the time zone ID from the host, use
// the default host timezone offset. Further refinements
// to this include querying the host to determine if DST
// is in use or not and possibly using the host locale to
// select from multiple zones at a the same offset. We
// don't do any of this now, but we could easily add this.
if (default_zone == NULL) {
// Use the designated default in the time zone list that has the
// appropriate GMT offset, if there is one.
const OffsetIndex* index = INDEX_BY_OFFSET;
for (;;) {
if (index->gmtOffset > rawOffset) {
// Went past our desired offset; no match found
break;
}
if (index->gmtOffset == rawOffset) {
// Found our desired offset
default_zone = createSystemTimeZone(ZONE_IDS[index->defaultZone]);
break;
}
// Compute the position of the next entry. If the delta value
// in this entry is zero, then there is no next entry.
uint16_t delta = index->nextEntryDelta;
if (delta == 0) {
break;
}
index = (const OffsetIndex*)((int8_t*)index + delta);
}
}
#endif
// Construct a fixed standard zone with the host's ID
// and raw offset.
if (default_zone == NULL) {
@ -669,7 +634,6 @@ TimeZone::adoptDefault(TimeZone* zone)
{
TimeZone* old = NULL;
umtx_init(&LOCK); /* This is here to prevent race conditions. */
umtx_lock(&LOCK);
old = DEFAULT_ZONE;
DEFAULT_ZONE = zone;
@ -1458,19 +1422,26 @@ TimeZone::getTZDataVersion(UErrorCode& status)
{
/* This is here to prevent race conditions. */
UBool needsInit;
UMTX_CHECK(&LOCK, (TZDATA_VERSION[0] == 0), needsInit);
UMTX_CHECK(&LOCK, !TZDataVersionInitialized, needsInit);
if (needsInit) {
int32_t len = sizeof(TZDATA_VERSION);
int32_t len = 0;
UResourceBundle *bundle = ures_openDirect(NULL, "zoneinfo", &status);
const UChar *tzver = ures_getStringByKey(bundle, "TZVersion",
&len, &status);
umtx_lock(&LOCK);
if (U_SUCCESS(status)) {
u_UCharsToChars(tzver, TZDATA_VERSION, len+1);
if (len >= 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);
}
umtx_unlock(&LOCK);
ures_close(bundle);
}

View File

@ -664,19 +664,21 @@ ZoneMeta::initialize(void) {
Hashtable *tmpMetaToOlson = createMetaToOlsonMap();
umtx_lock(&gZoneMetaLock);
if (gZoneMetaInitialized) {
// Another thread already created mappings
delete tmpCanonicalMap;
delete tmpOlsonToMeta;
delete tmpMetaToOlson;
} else {
if (!gZoneMetaInitialized) {
gCanonicalMap = tmpCanonicalMap;
gOlsonToMeta = tmpOlsonToMeta;
gMetaToOlson = tmpMetaToOlson;
tmpCanonicalMap = NULL;
tmpOlsonToMeta = NULL;
tmpMetaToOlson = NULL;
gZoneMetaInitialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
}
umtx_unlock(&gZoneMetaLock);
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
delete tmpCanonicalMap;
delete tmpOlsonToMeta;
delete tmpMetaToOlson;
}
UnicodeString& U_EXPORT2