TimeZoneGenericNames* TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) { if (U_FAILURE(status)) { return NULL; } TimeZoneGenericNames* instance = new TimeZoneGenericNames(); if (instance == NULL) { status = U_MEMORY_ALLOCATION_ERROR; return NULL; } TZGNCoreRef *cacheEntry = NULL; { Mutex lock(&gTZGNLock); if (!gTZGNCoreCacheInitialized) { // Create empty hashtable gTZGNCoreCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); if (U_SUCCESS(status)) { uhash_setKeyDeleter(gTZGNCoreCache, uprv_free); uhash_setValueDeleter(gTZGNCoreCache, deleteTZGNCoreRef); gTZGNCoreCacheInitialized = TRUE; ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEGENERICNAMES, tzgnCore_cleanup); } } if (U_FAILURE(status)) { return NULL; } // Check the cache, if not available, create new one and cache const char *key = locale.getName(); cacheEntry = (TZGNCoreRef *)uhash_get(gTZGNCoreCache, key); if (cacheEntry == NULL) { TZGNCore *tzgnCore = NULL; char *newKey = NULL; tzgnCore = new TZGNCore(locale, status); if (tzgnCore == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } if (U_SUCCESS(status)) { newKey = (char *)uprv_malloc(uprv_strlen(key) + 1); if (newKey == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { uprv_strcpy(newKey, key); } } if (U_SUCCESS(status)) { cacheEntry = (TZGNCoreRef *)uprv_malloc(sizeof(TZGNCoreRef)); if (cacheEntry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { cacheEntry->obj = tzgnCore; cacheEntry->refCount = 1; cacheEntry->lastAccess = (double)uprv_getUTCtime(); uhash_put(gTZGNCoreCache, newKey, cacheEntry, &status); } } if (U_FAILURE(status)) { if (tzgnCore != NULL) { delete tzgnCore; } if (newKey != NULL) { uprv_free(newKey); } if (cacheEntry != NULL) { uprv_free(cacheEntry); } cacheEntry = NULL; } } else { // Update the reference count cacheEntry->refCount++; cacheEntry->lastAccess = (double)uprv_getUTCtime(); } gAccessCount++; if (gAccessCount >= SWEEP_INTERVAL) { // sweep sweepCache(); gAccessCount = 0; } } // End of mutex locked block if (cacheEntry == NULL) { delete instance; return NULL; } instance->fRef = cacheEntry; return instance; }
TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status) { Mutex lock(&gTimeZoneNamesLock); if (!gTimeZoneNamesCacheInitialized) { // Create empty hashtable if it is not already initialized. gTimeZoneNamesCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status); if (U_SUCCESS(status)) { uhash_setKeyDeleter(gTimeZoneNamesCache, uprv_free); uhash_setValueDeleter(gTimeZoneNamesCache, deleteTimeZoneNamesCacheEntry); gTimeZoneNamesCacheInitialized = TRUE; ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONENAMES, timeZoneNames_cleanup); } } if (U_FAILURE(status)) { return; } // Check the cache, if not available, create new one and cache TimeZoneNamesCacheEntry *cacheEntry = NULL; const char *key = locale.getName(); cacheEntry = (TimeZoneNamesCacheEntry *)uhash_get(gTimeZoneNamesCache, key); if (cacheEntry == NULL) { TimeZoneNames *tznames = NULL; char *newKey = NULL; tznames = new TimeZoneNamesImpl(locale, status); if (tznames == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } if (U_SUCCESS(status)) { newKey = (char *)uprv_malloc(uprv_strlen(key) + 1); if (newKey == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { uprv_strcpy(newKey, key); } } if (U_SUCCESS(status)) { cacheEntry = (TimeZoneNamesCacheEntry *)uprv_malloc(sizeof(TimeZoneNamesCacheEntry)); if (cacheEntry == NULL) { status = U_MEMORY_ALLOCATION_ERROR; } else { cacheEntry->names = tznames; cacheEntry->refCount = 1; cacheEntry->lastAccess = (double)uprv_getUTCtime(); uhash_put(gTimeZoneNamesCache, newKey, cacheEntry, &status); } } if (U_FAILURE(status)) { if (tznames != NULL) { delete tznames; } if (newKey != NULL) { uprv_free(newKey); } if (cacheEntry != NULL) { uprv_free(cacheEntry); } cacheEntry = NULL; } } else { // Update the reference count cacheEntry->refCount++; cacheEntry->lastAccess = (double)uprv_getUTCtime(); } gAccessCount++; if (gAccessCount >= SWEEP_INTERVAL) { // sweep sweepCache(); gAccessCount = 0; } fTZnamesCacheEntry = cacheEntry; }