ICU-10051 Mutexes: introduce UInitOnce; remove UMTX_CHECK; replace all uses of UMTX_CHECK.

X-SVN-Rev: 33787
This commit is contained in:
Andy Heninger 2013-05-31 23:50:15 +00:00
parent 8ec350d593
commit 978f71fe78
51 changed files with 1274 additions and 2180 deletions

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003-2012, International Business Machines Corporation and *
* Copyright (C) 2003-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -124,12 +124,14 @@ void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& stat
}
#endif
// default century
const UDate BuddhistCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t BuddhistCalendar::fgSystemDefaultCenturyYear = -1;
UDate BuddhistCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t BuddhistCalendar::fgSystemDefaultCenturyStartYear = -1;
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Once the system default century date and year
* are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gBCInitOnce;
UBool BuddhistCalendar::haveDefaultCentury() const
@ -137,75 +139,40 @@ UBool BuddhistCalendar::haveDefaultCentury() const
return TRUE;
}
UDate BuddhistCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t BuddhistCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
BuddhistCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
BuddhistCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
BuddhistCalendar::initializeSystemDefaultCentury()
static void U_CALLCONV
initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
UErrorCode status = U_ZERO_ERROR;
BuddhistCalendar calendar(Locale("@calendar=buddhist"),status);
if (U_SUCCESS(status))
{
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) {
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
gSystemDefaultCenturyStartYear = newYear;
gSystemDefaultCenturyStart = newStart;
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate BuddhistCalendar::defaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart and systemDefaultCenturyStartYear
umtx_initOnce(gBCInitOnce, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t BuddhistCalendar::defaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear and systemDefaultCenturyStart
umtx_initOnce(gBCInitOnce, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 2003-2007, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************************
*
@ -189,49 +189,6 @@ private:
* @internal
*/
virtual int32_t defaultCenturyStartYear() const;
private: // default century stuff.
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates
* with 2-digit years are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with
* 2-digit years are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
};
U_NAMESPACE_END

View file

@ -60,6 +60,7 @@
#if !UCONFIG_NO_SERVICE
static icu::ICULocaleService* gService = NULL;
static UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
#endif
// INTERNAL - for cleanup
@ -71,6 +72,7 @@ static UBool calendar_cleanup(void) {
delete gService;
gService = NULL;
}
gServiceInitOnce.reset();
#endif
return TRUE;
}
@ -517,64 +519,51 @@ CalendarService::~CalendarService() {}
static inline UBool
isCalendarServiceUsed() {
UBool retVal;
UMTX_CHECK(NULL, gService != NULL, retVal);
return retVal;
return !gServiceInitOnce.isReset();
}
// -------------------------------------
static void U_CALLCONV
initCalendarService(UErrorCode &status)
{
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "Spinning up Calendar Service\n");
#endif
ucln_i18n_registerCleanup(UCLN_I18N_CALENDAR, calendar_cleanup);
gService = new CalendarService();
if (gService == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "Registering classes..\n");
#endif
// Register all basic instances.
gService->registerFactory(new BasicCalendarFactory(),status);
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "Done..\n");
#endif
if(U_FAILURE(status)) {
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "err (%s) registering classes, deleting service.....\n", u_errorName(status));
#endif
delete gService;
gService = NULL;
}
}
static ICULocaleService*
getCalendarService(UErrorCode &status)
{
UBool needInit;
UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
if (needInit) {
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "Spinning up Calendar Service\n");
#endif
ICULocaleService * newservice = new CalendarService();
if (newservice == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return newservice;
}
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "Registering classes..\n");
#endif
// Register all basic instances.
newservice->registerFactory(new BasicCalendarFactory(),status);
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "Done..\n");
#endif
if(U_FAILURE(status)) {
#ifdef U_DEBUG_CALSVC
fprintf(stderr, "err (%s) registering classes, deleting service.....\n", u_errorName(status));
#endif
delete newservice;
newservice = NULL;
}
if (newservice) {
umtx_lock(NULL);
if (gService == NULL) {
gService = newservice;
newservice = NULL;
}
umtx_unlock(NULL);
}
if (newservice) {
delete newservice;
} else {
// we won the contention - we can register the cleanup.
ucln_i18n_registerCleanup(UCLN_I18N_CALENDAR, calendar_cleanup);
}
}
umtx_initOnce(gServiceInitOnce, &initCalendarService, status);
return gService;
}
URegistryKey Calendar::registerFactory(ICUServiceFactory* toAdopt, UErrorCode& status)
{
return getCalendarService(status)->registerFactory(toAdopt, status);

View file

@ -54,7 +54,7 @@ static icu::CalendarAstronomer *gChineseCalendarAstro = NULL;
static icu::CalendarCache *gChineseCalendarWinterSolsticeCache = NULL;
static icu::CalendarCache *gChineseCalendarNewYearCache = NULL;
static icu::TimeZone *gChineseCalendarZoneAstroCalc = NULL;
static UBool gChineseCalendarZoneAstroCalcInitialized = FALSE;
static UInitOnce gChineseCalendarZoneAstroCalcInitOnce = U_INITONCE_INITIALIZER;
/**
* The start year of the Chinese calendar, the 61st year of the reign
@ -97,7 +97,7 @@ static UBool calendar_chinese_cleanup(void) {
delete gChineseCalendarZoneAstroCalc;
gChineseCalendarZoneAstroCalc = NULL;
}
gChineseCalendarZoneAstroCalcInitialized = FALSE;
gChineseCalendarZoneAstroCalcInitOnce.reset();
return TRUE;
}
U_CDECL_END
@ -150,20 +150,13 @@ const char *ChineseCalendar::getType() const {
return "chinese";
}
static void U_CALLCONV initChineseCalZoneAstroCalc() {
gChineseCalendarZoneAstroCalc = new SimpleTimeZone(CHINA_OFFSET, UNICODE_STRING_SIMPLE("CHINA_ZONE") );
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
const TimeZone* ChineseCalendar::getChineseCalZoneAstroCalc(void) const {
UBool initialized;
UMTX_CHECK(&astroLock, gChineseCalendarZoneAstroCalcInitialized, initialized);
if (!initialized) {
umtx_lock(&astroLock);
{
if (!gChineseCalendarZoneAstroCalcInitialized) {
gChineseCalendarZoneAstroCalc = new SimpleTimeZone(CHINA_OFFSET, UNICODE_STRING_SIMPLE("CHINA_ZONE") );
gChineseCalendarZoneAstroCalcInitialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_CHINESE_CALENDAR, calendar_chinese_cleanup);
}
}
umtx_unlock(&astroLock);
}
umtx_initOnce(gChineseCalendarZoneAstroCalcInitOnce, &initChineseCalZoneAstroCalc);
return gChineseCalendarZoneAstroCalc;
}
@ -842,11 +835,10 @@ ChineseCalendar::inDaylightTime(UErrorCode& status) const
}
// default century
const UDate ChineseCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t ChineseCalendar::fgSystemDefaultCenturyYear = -1;
UDate ChineseCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t ChineseCalendar::fgSystemDefaultCenturyStartYear = -1;
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInitOnce = U_INITONCE_INITIALIZER;
UBool ChineseCalendar::haveDefaultCentury() const
@ -864,66 +856,39 @@ int32_t ChineseCalendar::defaultCenturyStartYear() const
return internalGetDefaultCenturyStartYear();
}
UDate
ChineseCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
ChineseCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
ChineseCalendar::initializeSystemDefaultCentury()
static void U_CALLCONV initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
UErrorCode status = U_ZERO_ERROR;
ChineseCalendar calendar(Locale("@calendar=chinese"),status);
if (U_SUCCESS(status))
{
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
{
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate
ChineseCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInitOnce, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t
ChineseCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInitOnce, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ChineseCalendar)
U_NAMESPACE_END

View file

@ -259,28 +259,6 @@ class U_I18N_API ChineseCalendar : public Calendar {
virtual int32_t defaultCenturyStartYear() const;
private: // default century stuff.
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates
@ -294,13 +272,6 @@ class U_I18N_API ChineseCalendar : public Calendar {
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
ChineseCalendar(); // default constructor not implemented
};

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 1996-2012, International Business Machines Corporation and
* Copyright (C) 1996-2013, International Business Machines Corporation and
* others. All Rights Reserved.
******************************************************************************
*/
@ -50,6 +50,7 @@
#include "cmemory.h"
#include "umutex.h"
#include "servloc.h"
#include "uassert.h"
#include "ustrenum.h"
#include "uresimp.h"
#include "ucln_in.h"
@ -57,6 +58,8 @@
static icu::Locale* availableLocaleList = NULL;
static int32_t availableLocaleListCount;
static icu::ICULocaleService* gService = NULL;
static UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
static UInitOnce gAvailableLocaleListInitOnce;
/**
* Release all static memory held by collator.
@ -68,13 +71,14 @@ static UBool U_CALLCONV collator_cleanup(void) {
delete gService;
gService = NULL;
}
gServiceInitOnce.reset();
#endif
if (availableLocaleList) {
delete []availableLocaleList;
availableLocaleList = NULL;
}
availableLocaleListCount = 0;
gAvailableLocaleListInitOnce.reset();
return TRUE;
}
@ -199,28 +203,16 @@ ICUCollatorService::~ICUCollatorService() {}
// -------------------------------------
static void U_CALLCONV initService() {
gService = new ICUCollatorService();
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
}
static ICULocaleService*
getService(void)
{
UBool needInit;
UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
if(needInit) {
ICULocaleService *newservice = new ICUCollatorService();
if(newservice) {
umtx_lock(NULL);
if(gService == NULL) {
gService = newservice;
newservice = NULL;
}
umtx_unlock(NULL);
}
if(newservice) {
delete newservice;
}
else {
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
}
}
umtx_initOnce(gServiceInitOnce, &initService);
return gService;
}
@ -229,8 +221,7 @@ getService(void)
static inline UBool
hasService(void)
{
UBool retVal;
UMTX_CHECK(NULL, gService != NULL, retVal);
UBool retVal = !gServiceInitOnce.isReset() && (getService() != NULL);
return retVal;
}
@ -270,57 +261,44 @@ Collator::createUCollator(const char *loc,
}
#endif /* UCONFIG_NO_SERVICE */
static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
static void U_CALLCONV
initAvailableLocaleList(UErrorCode &status) {
U_ASSERT(availableLocaleListCount == 0);
U_ASSERT(availableLocaleList == NULL);
// for now, there is a hardcoded list, so just walk through that list and set it up.
UBool needInit;
UMTX_CHECK(NULL, availableLocaleList == NULL, needInit);
if (needInit) {
UResourceBundle *index = NULL;
UResourceBundle installed;
Locale * temp;
int32_t i = 0;
int32_t localeCount;
UResourceBundle *index = NULL;
UResourceBundle installed;
int32_t i = 0;
ures_initStackObject(&installed);
index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
ures_getByKey(index, "InstalledLocales", &installed, &status);
if(U_SUCCESS(status)) {
availableLocaleListCount = ures_getSize(&installed);
availableLocaleList = new Locale[availableLocaleListCount];
ures_initStackObject(&installed);
index = ures_openDirect(U_ICUDATA_COLL, "res_index", &status);
ures_getByKey(index, "InstalledLocales", &installed, &status);
if(U_SUCCESS(status)) {
localeCount = ures_getSize(&installed);
temp = new Locale[localeCount];
if (temp != NULL) {
ures_resetIterator(&installed);
while(ures_hasNext(&installed)) {
const char *tempKey = NULL;
ures_getNextString(&installed, NULL, &tempKey, &status);
temp[i++] = Locale(tempKey);
}
umtx_lock(NULL);
if (availableLocaleList == NULL)
{
availableLocaleListCount = localeCount;
availableLocaleList = temp;
temp = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
}
umtx_unlock(NULL);
needInit = FALSE;
if (temp) {
delete []temp;
}
if (availableLocaleList != NULL) {
ures_resetIterator(&installed);
while(ures_hasNext(&installed)) {
const char *tempKey = NULL;
ures_getNextString(&installed, NULL, &tempKey, &status);
availableLocaleList[i++] = Locale(tempKey);
}
ures_close(&installed);
}
ures_close(index);
U_ASSERT(availableLocaleListCount == i);
ures_close(&installed);
}
return !needInit;
ures_close(index);
ucln_i18n_registerCleanup(UCLN_I18N_COLLATOR, collator_cleanup);
}
static UBool isAvailableLocaleListInitialized(UErrorCode &status) {
umtx_initOnce(gAvailableLocaleListInitOnce, &initAvailableLocaleList, status);
return U_SUCCESS(status);
}
// Collator public methods -----------------------------------------------
Collator* U_EXPORT2 Collator::createInstance(UErrorCode& success)

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003 - 2009, International Business Machines Corporation and *
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -94,62 +94,46 @@ CopticCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/)
internalSet(UCAL_DAY_OF_YEAR, (30 * month) + day);
}
const UDate CopticCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t CopticCalendar::fgSystemDefaultCenturyYear = -1;
/**
* The system maintains a static default century start date and Year. They are
* initialized the first time they are used. Once the system default century date
* and year are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UDate CopticCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t CopticCalendar::fgSystemDefaultCenturyStartYear = -1;
static void U_CALLCONV initializeSystemDefaultCentury() {
UErrorCode status = U_ZERO_ERROR;
CopticCalendar calendar(Locale("@calendar=coptic"), status);
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate
CopticCalendar::defaultCenturyStart() const
{
initializeSystemDefaultCentury();
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t
CopticCalendar::defaultCenturyStartYear() const
{
initializeSystemDefaultCentury();
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStartYear;
}
void
CopticCalendar::initializeSystemDefaultCentury()
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (!needsUpdate) {
return;
}
UErrorCode status = U_ZERO_ERROR;
CopticCalendar calendar(Locale("@calendar=coptic"), status);
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
{
umtx_lock(NULL);
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
umtx_unlock(NULL);
}
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
int32_t
CopticCalendar::getJDEpochOffset() const
{

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003 - 2008, International Business Machines Corporation and *
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -188,36 +188,6 @@ protected:
*/
virtual int32_t getJDEpochOffset() const;
private:
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
public:
/**

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 2005-2012, International Business Machines
* Copyright (C) 2005-2013, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
*/
@ -32,13 +32,14 @@
#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
#define DELETE_ARRAY(array) uprv_free((void *) (array))
U_CDECL_BEGIN
static icu::CharsetRecognizer **fCSRecognizers = NULL;
static UInitOnce gCSRecognizersInitOnce;
static int32_t fCSRecognizers_size = 0;
U_CDECL_BEGIN
static UBool U_CALLCONV csdet_cleanup(void)
{
U_NAMESPACE_USE
if (fCSRecognizers != NULL) {
for(int32_t r = 0; r < fCSRecognizers_size; r += 1) {
delete fCSRecognizers[r];
@ -49,6 +50,7 @@ static UBool U_CALLCONV csdet_cleanup(void)
fCSRecognizers = NULL;
fCSRecognizers_size = 0;
}
gCSRecognizersInitOnce.reset();
return TRUE;
}
@ -65,96 +67,67 @@ charsetMatchComparator(const void * /*context*/, const void *left, const void *r
return (*csm_r)->getConfidence() - (*csm_l)->getConfidence();
}
static void U_CALLCONV initRecognizers(UErrorCode &status) {
U_NAMESPACE_USE
ucln_i18n_registerCleanup(UCLN_I18N_CSDET, csdet_cleanup);
CharsetRecognizer *tempArray[] = {
new CharsetRecog_UTF8(),
new CharsetRecog_UTF_16_BE(),
new CharsetRecog_UTF_16_LE(),
new CharsetRecog_UTF_32_BE(),
new CharsetRecog_UTF_32_LE(),
new CharsetRecog_8859_1(),
new CharsetRecog_8859_2(),
new CharsetRecog_8859_5_ru(),
new CharsetRecog_8859_6_ar(),
new CharsetRecog_8859_7_el(),
new CharsetRecog_8859_8_I_he(),
new CharsetRecog_8859_8_he(),
new CharsetRecog_windows_1251(),
new CharsetRecog_windows_1256(),
new CharsetRecog_KOI8_R(),
new CharsetRecog_8859_9_tr(),
new CharsetRecog_sjis(),
new CharsetRecog_gb_18030(),
new CharsetRecog_euc_jp(),
new CharsetRecog_euc_kr(),
new CharsetRecog_big5(),
new CharsetRecog_2022JP(),
new CharsetRecog_2022KR(),
new CharsetRecog_2022CN(),
new CharsetRecog_IBM424_he_rtl(),
new CharsetRecog_IBM424_he_ltr(),
new CharsetRecog_IBM420_ar_rtl(),
new CharsetRecog_IBM420_ar_ltr()
};
int32_t rCount = ARRAY_SIZE(tempArray);
fCSRecognizers = NEW_ARRAY(CharsetRecognizer *, rCount);
if (fCSRecognizers == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
} else {
fCSRecognizers_size = rCount;
for (int32_t r = 0; r < rCount; r += 1) {
fCSRecognizers[r] = tempArray[r];
if (fCSRecognizers[r] == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
}
}
U_CDECL_END
U_NAMESPACE_BEGIN
void CharsetDetector::setRecognizers(UErrorCode &status)
{
UBool needsInit;
CharsetRecognizer **recognizers;
if (U_FAILURE(status)) {
return;
}
UMTX_CHECK(NULL, (UBool) (fCSRecognizers == NULL), needsInit);
if (needsInit) {
CharsetRecognizer *tempArray[] = {
new CharsetRecog_UTF8(),
new CharsetRecog_UTF_16_BE(),
new CharsetRecog_UTF_16_LE(),
new CharsetRecog_UTF_32_BE(),
new CharsetRecog_UTF_32_LE(),
new CharsetRecog_8859_1(),
new CharsetRecog_8859_2(),
new CharsetRecog_8859_5_ru(),
new CharsetRecog_8859_6_ar(),
new CharsetRecog_8859_7_el(),
new CharsetRecog_8859_8_I_he(),
new CharsetRecog_8859_8_he(),
new CharsetRecog_windows_1251(),
new CharsetRecog_windows_1256(),
new CharsetRecog_KOI8_R(),
new CharsetRecog_8859_9_tr(),
new CharsetRecog_sjis(),
new CharsetRecog_gb_18030(),
new CharsetRecog_euc_jp(),
new CharsetRecog_euc_kr(),
new CharsetRecog_big5(),
new CharsetRecog_2022JP(),
new CharsetRecog_2022KR(),
new CharsetRecog_2022CN(),
new CharsetRecog_IBM424_he_rtl(),
new CharsetRecog_IBM424_he_ltr(),
new CharsetRecog_IBM420_ar_rtl(),
new CharsetRecog_IBM420_ar_ltr()
};
int32_t rCount = ARRAY_SIZE(tempArray);
int32_t r;
recognizers = NEW_ARRAY(CharsetRecognizer *, rCount);
if (recognizers == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
} else {
for (r = 0; r < rCount; r += 1) {
recognizers[r] = tempArray[r];
if (recognizers[r] == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
break;
}
}
}
if (U_SUCCESS(status)) {
umtx_lock(NULL);
if (fCSRecognizers == NULL) {
fCSRecognizers_size = rCount;
fCSRecognizers = recognizers;
}
umtx_unlock(NULL);
}
if (fCSRecognizers != recognizers) {
for (r = 0; r < rCount; r += 1) {
delete recognizers[r];
recognizers[r] = NULL;
}
DELETE_ARRAY(recognizers);
}
recognizers = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_CSDET, csdet_cleanup);
}
umtx_initOnce(gCSRecognizersInitOnce, &initRecognizers, status);
}
CharsetDetector::CharsetDetector(UErrorCode &status)

View file

@ -13,16 +13,16 @@
#if !UCONFIG_NO_FORMATTING
#include "umutex.h"
#include "gregoimp.h" // Math
#include "uassert.h"
#include "ucln_in.h"
#include "umutex.h"
#include "unicode/rbtz.h"
#include "unicode/tzrule.h"
#include "ucln_in.h"
// --- The cache --
static UMutex dangiLock = U_MUTEX_INITIALIZER;
static icu::TimeZone *gDangiCalendarZoneAstroCalc = NULL;
static UBool gDangiCalendarZoneAstroCalcInitialized = FALSE;
static UInitOnce gDangiCalendarInitOnce = U_INITONCE_INITIALIZER;
/**
* The start year of the Korean traditional calendar (Dan-gi) is the inaugural
@ -36,7 +36,7 @@ static UBool calendar_dangi_cleanup(void) {
delete gDangiCalendarZoneAstroCalc;
gDangiCalendarZoneAstroCalc = NULL;
}
gDangiCalendarZoneAstroCalcInitialized = FALSE;
gDangiCalendarInitOnce.reset();
return TRUE;
}
U_CDECL_END
@ -101,41 +101,36 @@ const char *DangiCalendar::getType() const {
* 1898-1911: GMT+8
* 1912- : GMT+9
*/
const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
UBool initialized;
UMTX_CHECK(&dangiLock, gDangiCalendarZoneAstroCalcInitialized, initialized);
if (!initialized) {
umtx_lock(&dangiLock);
{
if (!gDangiCalendarZoneAstroCalcInitialized) {
const UDate millis1897[] = { (UDate)((1897 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
const UDate millis1898[] = { (UDate)((1898 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
const UDate millis1912[] = { (UDate)((1912 - 1970) * 365 * kOneDay) }; // this doesn't create an issue for 1911/12/20
InitialTimeZoneRule* initialTimeZone = new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour, 0);
TimeZoneRule* rule1897 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour, 0, millis1897, 1, DateTimeRule::STANDARD_TIME);
TimeZoneRule* rule1898to1911 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour, 0, millis1898, 1, DateTimeRule::STANDARD_TIME);
TimeZoneRule* ruleFrom1912 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour, 0, millis1912, 1, DateTimeRule::STANDARD_TIME);
UErrorCode status = U_ZERO_ERROR;
RuleBasedTimeZone* dangiCalZoneAstroCalc = new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone); // adopts initialTimeZone
dangiCalZoneAstroCalc->addTransitionRule(rule1897, status); // adopts rule1897
dangiCalZoneAstroCalc->addTransitionRule(rule1898to1911, status);
dangiCalZoneAstroCalc->addTransitionRule(ruleFrom1912, status);
dangiCalZoneAstroCalc->complete(status);
if (U_SUCCESS(status)) {
gDangiCalendarZoneAstroCalc = dangiCalZoneAstroCalc;
} else {
delete dangiCalZoneAstroCalc;
gDangiCalendarZoneAstroCalc = NULL;
}
gDangiCalendarZoneAstroCalcInitialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup);
}
}
umtx_unlock(&dangiLock);
static void U_CALLCONV initDangiCalZoneAstroCalc(void) {
U_ASSERT(gDangiCalendarZoneAstroCalc == NULL);
const UDate millis1897[] = { (UDate)((1897 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
const UDate millis1898[] = { (UDate)((1898 - 1970) * 365 * kOneDay) }; // some days of error is not a problem here
const UDate millis1912[] = { (UDate)((1912 - 1970) * 365 * kOneDay) }; // this doesn't create an issue for 1911/12/20
InitialTimeZoneRule* initialTimeZone = new InitialTimeZoneRule(UNICODE_STRING_SIMPLE("GMT+8"), 8*kOneHour, 0);
TimeZoneRule* rule1897 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1897"), 7*kOneHour, 0, millis1897, 1, DateTimeRule::STANDARD_TIME);
TimeZoneRule* rule1898to1911 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1898-1911"), 8*kOneHour, 0, millis1898, 1, DateTimeRule::STANDARD_TIME);
TimeZoneRule* ruleFrom1912 = new TimeArrayTimeZoneRule(UNICODE_STRING_SIMPLE("Korean 1912-"), 9*kOneHour, 0, millis1912, 1, DateTimeRule::STANDARD_TIME);
UErrorCode status = U_ZERO_ERROR;
RuleBasedTimeZone* dangiCalZoneAstroCalc = new RuleBasedTimeZone(UNICODE_STRING_SIMPLE("KOREA_ZONE"), initialTimeZone); // adopts initialTimeZone
dangiCalZoneAstroCalc->addTransitionRule(rule1897, status); // adopts rule1897
dangiCalZoneAstroCalc->addTransitionRule(rule1898to1911, status);
dangiCalZoneAstroCalc->addTransitionRule(ruleFrom1912, status);
dangiCalZoneAstroCalc->complete(status);
if (U_SUCCESS(status)) {
gDangiCalendarZoneAstroCalc = dangiCalZoneAstroCalc;
} else {
delete dangiCalZoneAstroCalc;
gDangiCalendarZoneAstroCalc = NULL;
}
ucln_i18n_registerCleanup(UCLN_I18N_DANGI_CALENDAR, calendar_dangi_cleanup);
}
const TimeZone* DangiCalendar::getDangiCalZoneAstroCalc(void) const {
umtx_initOnce(gDangiCalendarInitOnce, &initDangiCalZoneAstroCalc);
return gDangiCalendarZoneAstroCalc;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DangiCalendar)
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2009-2011, International Business Machines Corporation and *
* Copyright (C) 2009-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -70,9 +70,7 @@ static const UChar gStrictDashEquivalentsPattern[] = {
0x005B, 0x005C, 0x002D, 0x2212, 0x005D, 0x0000};
DecimalFormatStaticSets *DecimalFormatStaticSets::gStaticSets = NULL;
DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode &status)
: fDotEquivalents(NULL),
fCommaEquivalents(NULL),
fOtherGroupingSeparators(NULL),
@ -84,15 +82,15 @@ DecimalFormatStaticSets::DecimalFormatStaticSets(UErrorCode *status)
fDefaultGroupingSeparators(NULL),
fStrictDefaultGroupingSeparators(NULL)
{
fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), *status);
fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), *status);
fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), *status);
fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), *status);
fDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gDotEquivalentsPattern, -1), status);
fCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gCommaEquivalentsPattern, -1), status);
fOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gOtherGroupingSeparatorsPattern, -1), status);
fDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gDashEquivalentsPattern, -1), status);
fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), *status);
fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), *status);
fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), *status);
fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), *status);
fStrictDotEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDotEquivalentsPattern, -1), status);
fStrictCommaEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictCommaEquivalentsPattern, -1), status);
fStrictOtherGroupingSeparators = new UnicodeSet(UnicodeString(TRUE, gStrictOtherGroupingSeparatorsPattern, -1), status);
fStrictDashEquivalents = new UnicodeSet(UnicodeString(TRUE, gStrictDashEquivalentsPattern, -1), status);
fDefaultGroupingSeparators = new UnicodeSet(*fDotEquivalents);
@ -137,7 +135,7 @@ ExitConstrDeleteAll: // Remove fPropSets and fRuleSets and return error
delete fStrictDefaultGroupingSeparators; fStrictDefaultGroupingSeparators = NULL;
delete fStrictOtherGroupingSeparators; fStrictOtherGroupingSeparators = NULL;
*status = U_MEMORY_ALLOCATION_ERROR;
status = U_MEMORY_ALLOCATION_ERROR;
}
@ -156,68 +154,50 @@ DecimalFormatStaticSets::~DecimalFormatStaticSets() {
}
static DecimalFormatStaticSets *gStaticSets;
static UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER;
//------------------------------------------------------------------------------
//
// decfmt_cleanup Memory cleanup function, free/delete all
// cached memory. Called by ICU's u_cleanup() function.
//
//------------------------------------------------------------------------------
UBool
DecimalFormatStaticSets::cleanup(void)
{
delete DecimalFormatStaticSets::gStaticSets;
DecimalFormatStaticSets::gStaticSets = NULL;
return TRUE;
}
U_CDECL_BEGIN
static UBool U_CALLCONV
decimfmt_cleanup(void)
{
return DecimalFormatStaticSets::cleanup();
delete gStaticSets;
gStaticSets = NULL;
gStaticSetsInitOnce.reset();
return TRUE;
}
static void U_CALLCONV initSets(UErrorCode &status) {
ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
gStaticSets = new DecimalFormatStaticSets(status);
if (U_FAILURE(status)) {
delete gStaticSets;
gStaticSets = NULL;
return;
}
if (gStaticSets == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
U_CDECL_END
void DecimalFormatStaticSets::initSets(UErrorCode *status)
{
DecimalFormatStaticSets *p;
UMTX_CHECK(NULL, gStaticSets, p);
if (p == NULL) {
p = new DecimalFormatStaticSets(status);
if (p == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return;
}
if (U_FAILURE(*status)) {
delete p;
return;
}
umtx_lock(NULL);
if (gStaticSets == NULL) {
gStaticSets = p;
p = NULL;
}
umtx_unlock(NULL);
if (p != NULL) {
delete p;
}
ucln_i18n_registerCleanup(UCLN_I18N_DECFMT, decimfmt_cleanup);
}
const DecimalFormatStaticSets *DecimalFormatStaticSets::getStaticSets(UErrorCode &status) {
umtx_initOnce(gStaticSetsInitOnce, initSets, status);
return gStaticSets;
}
const UnicodeSet *DecimalFormatStaticSets::getSimilarDecimals(UChar32 decimal, UBool strictParse)
{
UErrorCode status = U_ZERO_ERROR;
initSets(&status);
umtx_initOnce(gStaticSetsInitOnce, initSets, status);
if (U_FAILURE(status)) {
return NULL;
}

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2009-2011, International Business Machines Corporation and *
* Copyright (C) 2009-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -26,14 +26,15 @@ class UnicodeSet;
class DecimalFormatStaticSets : public UMemory
{
public:
static DecimalFormatStaticSets *gStaticSets; // Ptr to all lazily initialized constant
// shared sets.
DecimalFormatStaticSets(UErrorCode *status);
// Constructor and Destructor not for general use.
// Public to permit access from plain C implementation functions.
DecimalFormatStaticSets(UErrorCode &status);
~DecimalFormatStaticSets();
static void initSets(UErrorCode *status);
static UBool cleanup();
/**
* Return a pointer to a lazy-initialized singleton instance of this class.
*/
static const DecimalFormatStaticSets *getStaticSets(UErrorCode &status);
static const UnicodeSet *getSimilarDecimals(UChar32 decimal, UBool strictParse);

View file

@ -269,7 +269,7 @@ inline int32_t _max(int32_t a, int32_t b) { return (a<b) ? b : a; }
// Constructs a DecimalFormat instance in the default locale.
DecimalFormat::DecimalFormat(UErrorCode& status) {
init(status);
init();
UParseError parseError;
construct(status, parseError);
}
@ -280,7 +280,7 @@ DecimalFormat::DecimalFormat(UErrorCode& status) {
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
UErrorCode& status) {
init(status);
init();
UParseError parseError;
construct(status, parseError, &pattern);
}
@ -293,7 +293,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
DecimalFormatSymbols* symbolsToAdopt,
UErrorCode& status) {
init(status);
init();
UParseError parseError;
if (symbolsToAdopt == NULL)
status = U_ILLEGAL_ARGUMENT_ERROR;
@ -304,7 +304,7 @@ DecimalFormat::DecimalFormat( const UnicodeString& pattern,
DecimalFormatSymbols* symbolsToAdopt,
UParseError& parseErr,
UErrorCode& status) {
init(status);
init();
if (symbolsToAdopt == NULL)
status = U_ILLEGAL_ARGUMENT_ERROR;
construct(status,parseErr, &pattern, symbolsToAdopt);
@ -318,7 +318,7 @@ DecimalFormat::DecimalFormat( const UnicodeString& pattern,
DecimalFormat::DecimalFormat(const UnicodeString& pattern,
const DecimalFormatSymbols& symbols,
UErrorCode& status) {
init(status);
init();
UParseError parseError;
construct(status, parseError, &pattern, new DecimalFormatSymbols(symbols));
}
@ -332,7 +332,7 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
DecimalFormatSymbols* symbolsToAdopt,
UNumberFormatStyle style,
UErrorCode& status) {
init(status);
init();
fStyle = style;
UParseError parseError;
construct(status, parseError, &pattern, symbolsToAdopt);
@ -342,8 +342,10 @@ DecimalFormat::DecimalFormat(const UnicodeString& pattern,
// Common DecimalFormat initialization.
// Put all fields of an uninitialized object into a known state.
// Common code, shared by all constructors.
// Can not fail. Leave the object in good enough shape that the destructor
// or assignment operator can run successfully.
void
DecimalFormat::init(UErrorCode &status) {
DecimalFormat::init() {
fPosPrefixPattern = 0;
fPosSuffixPattern = 0;
fNegPrefixPattern = 0;
@ -382,8 +384,7 @@ DecimalFormat::init(UErrorCode &status) {
data.fFastFormatStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
data.fFastParseStatus=kFastpathUNKNOWN; // don't try to calculate the fastpath until later.
#endif
// only do this once per obj.
DecimalFormatStaticSets::initSets(&status);
fStaticSets = NULL;
}
//------------------------------------------------------------------------------
@ -392,7 +393,7 @@ DecimalFormat::init(UErrorCode &status) {
// created instance owns the symbols.
void
DecimalFormat::construct(UErrorCode& status,
DecimalFormat::construct(UErrorCode& status,
UParseError& parseErr,
const UnicodeString* pattern,
DecimalFormatSymbols* symbolsToAdopt)
@ -417,12 +418,15 @@ DecimalFormat::construct(UErrorCode& status,
if (fSymbols == NULL)
{
fSymbols = new DecimalFormatSymbols(Locale::getDefault(), status);
/* test for NULL */
if (fSymbols == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
}
fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
if (U_FAILURE(status)) {
return;
}
UErrorCode nsStatus = U_ZERO_ERROR;
NumberingSystem *ns = NumberingSystem::createInstance(nsStatus);
if (U_FAILURE(nsStatus)) {
@ -695,8 +699,7 @@ DecimalFormat::~DecimalFormat()
DecimalFormat::DecimalFormat(const DecimalFormat &source) :
NumberFormat(source) {
UErrorCode status = U_ZERO_ERROR;
init(status); // if this fails, 'source' isn't initialized properly either.
init();
*this = source;
}
@ -729,7 +732,9 @@ DecimalFormat&
DecimalFormat::operator=(const DecimalFormat& rhs)
{
if(this != &rhs) {
UErrorCode status = U_ZERO_ERROR;
NumberFormat::operator=(rhs);
fStaticSets = DecimalFormatStaticSets::getStaticSets(status);
fPositivePrefix = rhs.fPositivePrefix;
fPositiveSuffix = rhs.fPositiveSuffix;
fNegativePrefix = rhs.fNegativePrefix;
@ -2432,9 +2437,9 @@ UBool DecimalFormat::subparse(const UnicodeString& text,
if (groupingCharLength == groupingStringLength) {
if (strictParse) {
groupingSet = DecimalFormatStaticSets::gStaticSets->fStrictDefaultGroupingSeparators;
groupingSet = fStaticSets->fStrictDefaultGroupingSeparators;
} else {
groupingSet = DecimalFormatStaticSets::gStaticSets->fDefaultGroupingSeparators;
groupingSet = fStaticSets->fDefaultGroupingSeparators;
}
}
@ -2837,9 +2842,14 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
int32_t inputLength = input.length();
int32_t affixCharLength = U16_LENGTH(affixChar);
UnicodeSet *affixSet;
UErrorCode status = U_ZERO_ERROR;
const DecimalFormatStaticSets *staticSets = DecimalFormatStaticSets::getStaticSets(status);
if (U_FAILURE(status)) {
return -1;
}
if (!lenient) {
affixSet = DecimalFormatStaticSets::gStaticSets->fStrictDashEquivalents;
affixSet = staticSets->fStrictDashEquivalents;
// If the affix is exactly one character long and that character
// is in the dash set and the very next input character is also
@ -2905,7 +2915,7 @@ int32_t DecimalFormat::compareSimpleAffix(const UnicodeString& affix,
} else {
UBool match = FALSE;
affixSet = DecimalFormatStaticSets::gStaticSets->fDashEquivalents;
affixSet = staticSets->fDashEquivalents;
if (affixCharLength == affixLength && affixSet->contains(affixChar)) {
pos = skipUWhiteSpace(input, pos);

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003 - 2009, International Business Machines Corporation and *
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -134,58 +134,49 @@ EthiopicCalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType
return CECalendar::handleGetLimit(field, limitType);
}
const UDate EthiopicCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t EthiopicCalendar::fgSystemDefaultCenturyYear = -1;
/**
* The system maintains a static default century start date and Year. They are
* initialized the first time they are used. Once the system default century date
* and year are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UDate EthiopicCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t EthiopicCalendar::fgSystemDefaultCenturyStartYear = -1;
static void U_CALLCONV initializeSystemDefaultCentury()
{
UErrorCode status = U_ZERO_ERROR;
EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status);
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate
EthiopicCalendar::defaultCenturyStart() const
{
initializeSystemDefaultCentury();
return fgSystemDefaultCenturyStart;
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t
EthiopicCalendar::defaultCenturyStartYear() const
{
initializeSystemDefaultCentury();
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
if (isAmeteAlemEra()) {
return fgSystemDefaultCenturyStartYear + AMETE_MIHRET_DELTA;
return gSystemDefaultCenturyStartYear + AMETE_MIHRET_DELTA;
}
return fgSystemDefaultCenturyStartYear;
return gSystemDefaultCenturyStartYear;
}
void
EthiopicCalendar::initializeSystemDefaultCentury()
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (!needsUpdate) {
return;
}
UErrorCode status = U_ZERO_ERROR;
EthiopicCalendar calendar(Locale("@calendar=ethiopic"), status);
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
{
umtx_lock(NULL);
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
umtx_unlock(NULL);
}
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
int32_t
EthiopicCalendar::getJDEpochOffset() const

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003 - 2008, International Business Machines Corporation and *
* Copyright (C) 2003 - 2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
@ -205,36 +205,6 @@ protected:
virtual int32_t getJDEpochOffset() const;
private:
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
/**
* When eraType is AMETE_ALEM_ERA, then this calendar use only AMETE_ALEM
* for the era. Otherwise (default), this calendar uses both AMETE_ALEM

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2008-2012, International Business Machines Corporation and
* Copyright (C) 2008-2013, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
@ -24,6 +24,7 @@
#include "cmemory.h"
#include "cstring.h"
#include "mutex.h"
#include "uassert.h"
#include "ucln_in.h"
#include "umutex.h"
#include "uhash.h"
@ -34,6 +35,7 @@ static const char* gNeutralStr = "neutral";
static const char* gMailTaintsStr = "maleTaints";
static const char* gMixedNeutralStr = "mixedNeutral";
static icu::GenderInfo* gObjs = NULL;
static UInitOnce gGenderInitOnce = U_INITONCE_INITIALIZER;
enum GenderStyle {
NEUTRAL,
@ -50,6 +52,7 @@ static UBool U_CALLCONV gender_cleanup(void) {
gGenderInfoCache = NULL;
delete [] gObjs;
}
gGenderInitOnce.reset();
return TRUE;
}
@ -57,6 +60,29 @@ U_CDECL_END
U_NAMESPACE_BEGIN
void U_CALLCONV GenderInfo_initCache(UErrorCode &status) {
ucln_i18n_registerCleanup(UCLN_I18N_GENDERINFO, gender_cleanup);
U_ASSERT(gGenderInfoCache == NULL);
if (U_FAILURE(status)) {
return;
}
gObjs = new GenderInfo[GENDER_STYLE_LENGTH];
if (gObjs == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
for (int i = 0; i < GENDER_STYLE_LENGTH; i++) {
gObjs[i]._style = i;
}
gGenderInfoCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
if (U_FAILURE(status)) {
delete [] gObjs;
return;
}
uhash_setKeyDeleter(gGenderInfoCache, uprv_free);
}
GenderInfo::GenderInfo() {
}
@ -64,34 +90,12 @@ GenderInfo::~GenderInfo() {
}
const GenderInfo* GenderInfo::getInstance(const Locale& locale, UErrorCode& status) {
// Make sure our cache exists.
umtx_initOnce(gGenderInitOnce, &GenderInfo_initCache, status);
if (U_FAILURE(status)) {
return NULL;
}
// Make sure our cache exists.
UBool needed;
UMTX_CHECK(&gGenderMetaLock, (gGenderInfoCache == NULL), needed);
if (needed) {
Mutex lock(&gGenderMetaLock);
if (gGenderInfoCache == NULL) {
gObjs = new GenderInfo[GENDER_STYLE_LENGTH];
if (gObjs == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return NULL;
}
for (int i = 0; i < GENDER_STYLE_LENGTH; i++) {
gObjs[i]._style = i;
}
gGenderInfoCache = uhash_open(uhash_hashChars, uhash_compareChars, NULL, &status);
if (U_FAILURE(status)) {
delete [] gObjs;
return NULL;
}
uhash_setKeyDeleter(gGenderInfoCache, uprv_free);
ucln_i18n_registerCleanup(UCLN_I18N_GENDERINFO, gender_cleanup);
}
}
const GenderInfo* result = NULL;
const char* key = locale.getName();
{

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1997-2012, International Business Machines Corporation and *
* Copyright (C) 1997-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -1264,11 +1264,14 @@ GregorianCalendar::getType() const {
return "gregorian";
}
const UDate GregorianCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t GregorianCalendar::fgSystemDefaultCenturyYear = -1;
UDate GregorianCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t GregorianCalendar::fgSystemDefaultCenturyStartYear = -1;
/**
* The system maintains a static default century start date and Year. They are
* initialized the first time they are used. Once the system default century date
* and year are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UBool GregorianCalendar::haveDefaultCentury() const
@ -1276,78 +1279,36 @@ UBool GregorianCalendar::haveDefaultCentury() const
return TRUE;
}
UDate GregorianCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t GregorianCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
GregorianCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
GregorianCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
GregorianCalendar::initializeSystemDefaultCentury()
static void U_CALLCONV
initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
UErrorCode status = U_ZERO_ERROR;
Calendar *calendar = new GregorianCalendar(status);
if (calendar != NULL && U_SUCCESS(status))
{
calendar->setTime(Calendar::getNow(), status);
calendar->add(UCAL_YEAR, -80, status);
GregorianCalendar calendar(status);
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar->getTime(status);
int32_t newYear = calendar->get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
{
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
delete calendar;
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate GregorianCalendar::defaultCenturyStart() const {
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t GregorianCalendar::defaultCenturyStartYear() const {
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2011, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
@ -668,88 +668,52 @@ HebrewCalendar::inDaylightTime(UErrorCode& status) const
return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
}
// default century
const UDate HebrewCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t HebrewCalendar::fgSystemDefaultCenturyYear = -1;
UDate HebrewCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t HebrewCalendar::fgSystemDefaultCenturyStartYear = -1;
/**
* The system maintains a static default century start date and Year. They are
* initialized the first time they are used. Once the system default century date
* and year are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UBool HebrewCalendar::haveDefaultCentury() const
{
return TRUE;
}
UDate HebrewCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t HebrewCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
HebrewCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
HebrewCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
HebrewCalendar::initializeSystemDefaultCentury()
static void U_CALLCONV initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
UErrorCode status = U_ZERO_ERROR;
HebrewCalendar calendar(Locale("@calendar=hebrew"),status);
if (U_SUCCESS(status))
{
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury) {
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate HebrewCalendar::defaultCenturyStart() const {
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t HebrewCalendar::defaultCenturyStartYear() const {
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(HebrewCalendar)
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2009, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
@ -395,49 +395,6 @@ public:
*/
virtual int32_t defaultCenturyStartYear() const;
private: // default century stuff.
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates
* with 2-digit years are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with
* 2-digit years are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
private: // Calendar-specific implementation
/**
* Finds the day # of the first day in the given Hebrew year.

View file

@ -91,7 +91,7 @@
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<DisableLanguageExtensions>true</DisableLanguageExtensions>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x86\Release/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x86\Release/</AssemblerListingLocation>
@ -133,7 +133,7 @@
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<DisableLanguageExtensions>true</DisableLanguageExtensions>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x86\Debug/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x86\Debug/</AssemblerListingLocation>
@ -176,7 +176,7 @@
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
<DisableLanguageExtensions>true</DisableLanguageExtensions>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x64\Release/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x64\Release/</AssemblerListingLocation>
@ -216,7 +216,7 @@
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<BufferSecurityCheck>true</BufferSecurityCheck>
<DisableLanguageExtensions>true</DisableLanguageExtensions>
<DisableLanguageExtensions>false</DisableLanguageExtensions>
<TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
<PrecompiledHeaderOutputFile>.\x64\Debug/i18n.pch</PrecompiledHeaderOutputFile>
<AssemblerListingLocation>.\x64\Debug/</AssemblerListingLocation>

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2012, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
@ -457,89 +457,51 @@ IslamicCalendar::inDaylightTime(UErrorCode& status) const
return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE);
}
// default century
const UDate IslamicCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t IslamicCalendar::fgSystemDefaultCenturyYear = -1;
UDate IslamicCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t IslamicCalendar::fgSystemDefaultCenturyStartYear = -1;
/**
* The system maintains a static default century start date and Year. They are
* initialized the first time they are used. Once the system default century date
* and year are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UBool IslamicCalendar::haveDefaultCentury() const
{
return TRUE;
}
UDate IslamicCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t IslamicCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
IslamicCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
IslamicCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
IslamicCalendar::initializeSystemDefaultCentury()
static void U_CALLCONV initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
UErrorCode status = U_ZERO_ERROR;
IslamicCalendar calendar(Locale("@calendar=islamic-civil"),status);
if (U_SUCCESS(status))
{
if (U_SUCCESS(status)) {
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
{
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate IslamicCalendar::defaultCenturyStart() const {
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t IslamicCalendar::defaultCenturyStartYear() const {
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IslamicCalendar)
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 2003-2009, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
@ -409,49 +409,6 @@ class IslamicCalendar : public Calendar {
* @internal
*/
virtual int32_t defaultCenturyStartYear() const;
private: // default century stuff.
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates
* with 2-digit years are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with
* 2-digit years are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
};
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 1997-2012, International Business Machines Corporation and *
* Copyright (C) 1997-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -45,6 +45,7 @@
#include "ucln_in.h"
#include "cstring.h"
#include "putilimp.h"
#include "uassert.h"
#include "umutex.h"
#include "mutex.h"
#include "digitlst.h"
@ -138,11 +139,12 @@ static const char *gFormatKeys[UNUM_FORMAT_STYLE_COUNT] = {
// Static hashtable cache of NumberingSystem objects used by NumberFormat
static UHashtable * NumberingSystem_cache = NULL;
static UMutex nscacheMutex = U_MUTEX_INITIALIZER;
static UInitOnce gNSCacheInitOnce = U_INITONCE_INITIALIZER;
#if !UCONFIG_NO_SERVICE
static icu::ICULocaleService* gService = NULL;
static UInitOnce gServiceInitOnce = U_INITONCE_INITIALIZER;
#endif
/**
@ -156,11 +158,13 @@ deleteNumberingSystem(void *obj) {
static UBool U_CALLCONV numfmt_cleanup(void) {
#if !UCONFIG_NO_SERVICE
gServiceInitOnce.reset();
if (gService) {
delete gService;
gService = NULL;
}
#endif
gNSCacheInitOnce.reset();
if (NumberingSystem_cache) {
// delete NumberingSystem_cache;
uhash_close(NumberingSystem_cache);
@ -902,31 +906,23 @@ ICUNumberFormatService::~ICUNumberFormatService() {}
// -------------------------------------
static void U_CALLCONV initNumberFormatService() {
U_ASSERT(gService == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
gService = new ICUNumberFormatService();
}
static ICULocaleService*
getNumberFormatService(void)
{
UBool needInit;
UMTX_CHECK(NULL, (UBool)(gService == NULL), needInit);
if (needInit) {
ICULocaleService * newservice = new ICUNumberFormatService();
if (newservice) {
umtx_lock(NULL);
if (gService == NULL) {
gService = newservice;
newservice = NULL;
}
umtx_unlock(NULL);
}
if (newservice) {
delete newservice;
} else {
// we won the contention, this thread can register cleanup.
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
}
}
umtx_initOnce(gServiceInitOnce, &initNumberFormatService);
return gService;
}
static UBool haveService() {
return !gServiceInitOnce.isReset() && (getNumberFormatService() != NULL);
}
// -------------------------------------
URegistryKey U_EXPORT2
@ -948,15 +944,15 @@ NumberFormat::registerFactory(NumberFormatFactory* toAdopt, UErrorCode& status)
UBool U_EXPORT2
NumberFormat::unregister(URegistryKey key, UErrorCode& status)
{
if (U_SUCCESS(status)) {
UBool haveService;
UMTX_CHECK(NULL, gService != NULL, haveService);
if (haveService) {
return gService->unregister(key, status);
}
status = U_ILLEGAL_ARGUMENT_ERROR;
if (U_FAILURE(status)) {
return FALSE;
}
if (haveService()) {
return gService->unregister(key, status);
} else {
status = U_ILLEGAL_ARGUMENT_ERROR;
return FALSE;
}
return FALSE;
}
// -------------------------------------
@ -965,7 +961,7 @@ NumberFormat::getAvailableLocales(void)
{
ICULocaleService *service = getNumberFormatService();
if (service) {
return service->getAvailableLocales();
return service->getAvailableLocales();
}
return NULL; // no way to return error condition
}
@ -973,19 +969,13 @@ NumberFormat::getAvailableLocales(void)
// -------------------------------------
NumberFormat* U_EXPORT2
NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status)
{
NumberFormat::createInstance(const Locale& loc, UNumberFormatStyle kind, UErrorCode& status) {
#if !UCONFIG_NO_SERVICE
UBool haveService;
UMTX_CHECK(NULL, gService != NULL, haveService);
if (haveService) {
if (haveService()) {
return (NumberFormat*)gService->get(loc, kind, status);
}
else
#endif
{
return makeInstance(loc, kind, status);
}
return makeInstance(loc, kind, status);
}
@ -1132,6 +1122,22 @@ void NumberFormat::getEffectiveCurrency(UChar* result, UErrorCode& ec) const {
// Creates the NumberFormat instance of the specified style (number, currency,
// or percent) for the desired locale.
static void U_CALLCONV nscacheInit() {
U_ASSERT(NumberingSystem_cache == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
UErrorCode status = U_ZERO_ERROR;
NumberingSystem_cache = uhash_open(uhash_hashLong,
uhash_compareLong,
NULL,
&status);
if (U_FAILURE(status)) {
// Number Format code will run with no cache if creation fails.
NumberingSystem_cache = NULL;
return;
}
uhash_setValueDeleter(NumberingSystem_cache, deleteNumberingSystem);
}
UBool
NumberFormat::isStyleSupported(UNumberFormatStyle style) {
return gLastResortNumberPatterns[style] != NULL;
@ -1200,48 +1206,20 @@ NumberFormat::makeInstance(const Locale& desiredLocale,
}
#endif
// Use numbering system cache hashtable
UHashtable *cache;
UMTX_CHECK(&nscacheMutex, NumberingSystem_cache, cache);
// Check cache we got, create if non-existant
if (cache == NULL) {
cache = uhash_open(uhash_hashLong,
uhash_compareLong,
NULL,
&status);
if (U_FAILURE(status)) {
// cache not created - out of memory
status = U_ZERO_ERROR; // work without the cache
cache = NULL;
} else {
// cache created
uhash_setValueDeleter(cache, deleteNumberingSystem);
// set final NumberingSystem_cache value
Mutex lock(&nscacheMutex);
if (NumberingSystem_cache == NULL) {
NumberingSystem_cache = cache;
ucln_i18n_registerCleanup(UCLN_I18N_NUMFMT, numfmt_cleanup);
} else {
uhash_close(cache);
cache = NumberingSystem_cache;
}
}
}
umtx_initOnce(gNSCacheInitOnce, &nscacheInit);
// Get cached numbering system
LocalPointer<NumberingSystem> ownedNs;
NumberingSystem *ns = NULL;
if (cache != NULL) {
if (NumberingSystem_cache != NULL) {
// TODO: Bad hash key usage, see ticket #8504.
int32_t hashKey = desiredLocale.hashCode();
Mutex lock(&nscacheMutex);
ns = (NumberingSystem *)uhash_iget(cache, hashKey);
ns = (NumberingSystem *)uhash_iget(NumberingSystem_cache, hashKey);
if (ns == NULL) {
ns = NumberingSystem::createInstance(desiredLocale,status);
uhash_iput(cache, hashKey, (void*)ns, &status);
uhash_iput(NumberingSystem_cache, hashKey, (void*)ns, &status);
}
} else {
ownedNs.adoptInstead(NumberingSystem::createInstance(desiredLocale,status));

View file

@ -119,7 +119,7 @@ OlsonTimeZone::OlsonTimeZone(const UResourceBundle* top,
const UResourceBundle* res,
const UnicodeString& tzid,
UErrorCode& ec) :
BasicTimeZone(tzid), finalZone(NULL), transitionRulesInitialized(FALSE)
BasicTimeZone(tzid), finalZone(NULL)
{
clearTransitionRules();
U_DEBUG_TZ_MSG(("OlsonTimeZone(%s)\n", ures_getKey((UResourceBundle*)res)));
@ -658,7 +658,7 @@ OlsonTimeZone::clearTransitionRules(void) {
historicRuleCount = 0;
finalZoneWithStartYear = NULL;
firstTZTransitionIdx = 0;
transitionRulesInitialized = FALSE;
transitionRulesInitOnce.reset();
}
void
@ -689,23 +689,15 @@ OlsonTimeZone::deleteTransitionRules(void) {
/*
* Lazy transition rules initializer
*/
static UMutex gLock = U_MUTEX_INITIALIZER;
static void U_CALLCONV initRules(OlsonTimeZone *This, UErrorCode &status) {
This->initTransitionRules(status);
}
void
OlsonTimeZone::checkTransitionRules(UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
UBool initialized;
UMTX_CHECK(&gLock, transitionRulesInitialized, initialized);
if (!initialized) {
umtx_lock(&gLock);
if (!transitionRulesInitialized) {
OlsonTimeZone *ncThis = const_cast<OlsonTimeZone*>(this);
ncThis->initTransitionRules(status);
}
umtx_unlock(&gLock);
}
OlsonTimeZone *ncThis = const_cast<OlsonTimeZone *>(this);
umtx_initOnce(ncThis->transitionRulesInitOnce, &initRules, ncThis, status);
}
void
@ -713,9 +705,6 @@ OlsonTimeZone::initTransitionRules(UErrorCode& status) {
if(U_FAILURE(status)) {
return;
}
if (transitionRulesInitialized) {
return;
}
deleteTransitionRules();
UnicodeString tzid;
getID(tzid);
@ -884,7 +873,6 @@ OlsonTimeZone::initTransitionRules(UErrorCode& status) {
firstFinalTZTransition->adoptFrom(prevRule->clone());
firstFinalTZTransition->adoptTo(firstFinalRule);
}
transitionRulesInitialized = TRUE;
}
UBool

View file

@ -16,6 +16,7 @@
#if !UCONFIG_NO_FORMATTING
#include "unicode/basictz.h"
#include "umutex.h"
struct UResourceBundle;
@ -383,7 +384,10 @@ private:
void clearTransitionRules(void);
void deleteTransitionRules(void);
void checkTransitionRules(UErrorCode& status) const;
public: // Internal, for access from plain C code
void initTransitionRules(UErrorCode& status);
private:
InitialTimeZoneRule *initialRule;
TimeZoneTransition *firstTZTransition;
@ -392,7 +396,7 @@ private:
TimeArrayTimeZoneRule **historicRules;
int16_t historicRuleCount;
SimpleTimeZone *finalZoneWithStartYear; // hack
UBool transitionRulesInitialized;
UInitOnce transitionRulesInitOnce;
};
inline int16_t

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2012, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
@ -245,64 +245,17 @@ PersianCalendar::inDaylightTime(UErrorCode& status) const
}
// default century
const UDate PersianCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t PersianCalendar::fgSystemDefaultCenturyYear = -1;
UDate PersianCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t PersianCalendar::fgSystemDefaultCenturyStartYear = -1;
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UBool PersianCalendar::haveDefaultCentury() const
{
return TRUE;
}
UDate PersianCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t PersianCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
PersianCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
PersianCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
PersianCalendar::initializeSystemDefaultCentury()
{
static void U_CALLCONV initializeSystemDefaultCentury() {
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
// the current time.
@ -312,20 +265,26 @@ PersianCalendar::initializeSystemDefaultCentury()
{
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
{
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate PersianCalendar::defaultCenturyStart() const {
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t PersianCalendar::defaultCenturyStartYear() const {
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(PersianCalendar)
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
******************************************************************************
* Copyright (C) 2003-2008, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
******************************************************************************
*
@ -310,49 +310,6 @@ class PersianCalendar : public Calendar {
* @internal
*/
virtual int32_t defaultCenturyStartYear() const;
private: // default century stuff.
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates
* with 2-digit years are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with
* 2-digit years are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
};
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
**********************************************************************
* Copyright (C) 1999-2012, International Business Machines
* Copyright (C) 1999-2013, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Date Name Description
@ -248,8 +248,11 @@ RuleBasedTransliterator::handleTransliterate(Replaceable& text, UTransPosition&
// some other transliteration that is still in progress and holding the
// transliteration mutex. If so, do not lock the transliteration
// mutex again.
// TODO(andy): Need a better scheme for handling this.
UBool needToLock;
UMTX_CHECK(NULL, (&text != gLockedText), needToLock);
umtx_lock(NULL);
needToLock = (&text != gLockedText);
umtx_unlock(NULL);
if (needToLock) {
umtx_lock(&transliteratorDataMutex);
gLockedText = &text;

View file

@ -151,16 +151,12 @@ RuleBasedTimeZone::completeConst(UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
UBool updated;
UMTX_CHECK(&gLock, fUpToDate, updated);
if (!updated) {
umtx_lock(&gLock);
if (!fUpToDate) {
RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this);
ncThis->complete(status);
}
umtx_unlock(&gLock);
umtx_lock(&gLock);
if (!fUpToDate) {
RuleBasedTimeZone *ncThis = const_cast<RuleBasedTimeZone*>(this);
ncThis->complete(status);
}
umtx_unlock(&gLock);
}
void

View file

@ -1,7 +1,7 @@
//
// regexst.h
//
// Copyright (C) 2004-2012, International Business Machines Corporation and others.
// Copyright (C) 2004-2013, International Business Machines Corporation and others.
// All Rights Reserved.
//
// This file contains class RegexStaticSets
@ -144,6 +144,7 @@ static const UChar gGC_LVTPattern[] = {
RegexStaticSets *RegexStaticSets::gStaticSets = NULL;
UInitOnce gStaticSetsInitOnce = U_INITONCE_INITIALIZER;
RegexStaticSets::RegexStaticSets(UErrorCode *status)
:
@ -255,6 +256,7 @@ UBool
RegexStaticSets::cleanup(void) {
delete RegexStaticSets::gStaticSets;
RegexStaticSets::gStaticSets = NULL;
gStaticSetsInitOnce.reset();
return TRUE;
}
@ -263,34 +265,24 @@ static UBool U_CALLCONV
regex_cleanup(void) {
return RegexStaticSets::cleanup();
}
static void U_CALLCONV initStaticSets(UErrorCode &status) {
U_ASSERT(RegexStaticSets::gStaticSets == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_REGEX, regex_cleanup);
RegexStaticSets::gStaticSets = new RegexStaticSets(&status);
if (U_FAILURE(status)) {
delete RegexStaticSets::gStaticSets;
RegexStaticSets::gStaticSets = NULL;
}
if (RegexStaticSets::gStaticSets == NULL && U_SUCCESS(status)) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
U_CDECL_END
void RegexStaticSets::initGlobals(UErrorCode *status) {
RegexStaticSets *p;
UMTX_CHECK(NULL, gStaticSets, p);
if (p == NULL) {
p = new RegexStaticSets(status);
if (p == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return;
}
if (U_FAILURE(*status)) {
delete p;
return;
}
umtx_lock(NULL);
if (gStaticSets == NULL) {
gStaticSets = p;
p = NULL;
}
umtx_unlock(NULL);
if (p) {
delete p;
}
ucln_i18n_registerCleanup(UCLN_I18N_REGEX, regex_cleanup);
}
umtx_initOnce(gStaticSetsInitOnce, &initStaticSets, *status);
}
U_NAMESPACE_END
#endif // !UCONFIG_NO_REGULAR_EXPRESSIONS

View file

@ -1063,6 +1063,17 @@ SimpleTimeZone::deleteTransitionRules(void) {
/*
* Lazy transition rules initializer
*
* Note On the removal of UMTX_CHECK from checkTransitionRules():
*
* It would be faster to have a UInitOnce as part of a SimpleTimeZone object,
* which would avoid needing to lock a mutex to check the initialization state.
* But we can't easily because simpletz.h is a public header, and including
* a UInitOnce as a member of SimpleTimeZone would publicly expose internal ICU headers.
*
* Alternatively we could have a pointer to a UInitOnce in the SimpleTimeZone object,
* allocate it in the constructors. This would be a more intrusive change, but doable
* if performance turns out to be an issue.
*/
static UMutex gLock = U_MUTEX_INITIALIZER;
@ -1071,16 +1082,12 @@ SimpleTimeZone::checkTransitionRules(UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
UBool initialized;
UMTX_CHECK(&gLock, transitionRulesInitialized, initialized);
if (!initialized) {
umtx_lock(&gLock);
if (!transitionRulesInitialized) {
SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
ncThis->initTransitionRules(status);
}
umtx_unlock(&gLock);
umtx_lock(&gLock);
if (!transitionRulesInitialized) {
SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
ncThis->initTransitionRules(status);
}
umtx_unlock(&gLock);
}
void

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2009-2011, International Business Machines Corporation and *
* Copyright (C) 2009-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -18,6 +18,7 @@
#include "unicode/uniset.h"
#include "unicode/udat.h"
#include "cmemory.h"
#include "uassert.h"
#include "ucln_in.h"
#include "umutex.h"
@ -26,16 +27,17 @@
U_NAMESPACE_BEGIN
SimpleDateFormatStaticSets *SimpleDateFormatStaticSets::gStaticSets = NULL;
SimpleDateFormatStaticSets *gStaticSets = NULL;
UInitOnce gSimpleDateFormatStaticSetsInitOnce = U_INITONCE_INITIALIZER;
SimpleDateFormatStaticSets::SimpleDateFormatStaticSets(UErrorCode *status)
SimpleDateFormatStaticSets::SimpleDateFormatStaticSets(UErrorCode &status)
: fDateIgnorables(NULL),
fTimeIgnorables(NULL),
fOtherIgnorables(NULL)
{
fDateIgnorables = new UnicodeSet(UNICODE_STRING("[-,./[:whitespace:]]", 20), *status);
fTimeIgnorables = new UnicodeSet(UNICODE_STRING("[-.:[:whitespace:]]", 19), *status);
fOtherIgnorables = new UnicodeSet(UNICODE_STRING("[:whitespace:]", 14), *status);
fDateIgnorables = new UnicodeSet(UNICODE_STRING("[-,./[:whitespace:]]", 20), status);
fTimeIgnorables = new UnicodeSet(UNICODE_STRING("[-.:[:whitespace:]]", 19), status);
fOtherIgnorables = new UnicodeSet(UNICODE_STRING("[:whitespace:]", 14), status);
// Check for null pointers
if (fDateIgnorables == NULL || fTimeIgnorables == NULL || fOtherIgnorables == NULL) {
@ -54,7 +56,7 @@ ExitConstrDeleteAll: // Remove all sets and return error
delete fTimeIgnorables; fTimeIgnorables = NULL;
delete fOtherIgnorables; fOtherIgnorables = NULL;
*status = U_MEMORY_ALLOCATION_ERROR;
status = U_MEMORY_ALLOCATION_ERROR;
}
@ -74,9 +76,9 @@ SimpleDateFormatStaticSets::~SimpleDateFormatStaticSets() {
UBool
SimpleDateFormatStaticSets::cleanup(void)
{
delete SimpleDateFormatStaticSets::gStaticSets;
SimpleDateFormatStaticSets::gStaticSets = NULL;
delete gStaticSets;
gStaticSets = NULL;
gSimpleDateFormatStaticSetsInitOnce.reset();
return TRUE;
}
@ -86,50 +88,26 @@ smpdtfmt_cleanup(void)
{
return SimpleDateFormatStaticSets::cleanup();
}
U_CDECL_END
void SimpleDateFormatStaticSets::initSets(UErrorCode *status)
{
SimpleDateFormatStaticSets *p;
UMTX_CHECK(NULL, gStaticSets, p);
if (p == NULL) {
p = new SimpleDateFormatStaticSets(status);
if (p == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
return;
}
if (U_FAILURE(*status)) {
delete p;
return;
}
umtx_lock(NULL);
if (gStaticSets == NULL) {
gStaticSets = p;
p = NULL;
}
umtx_unlock(NULL);
if (p != NULL) {
delete p;
}
ucln_i18n_registerCleanup(UCLN_I18N_SMPDTFMT, smpdtfmt_cleanup);
static void U_CALLCONV smpdtfmt_initSets(UErrorCode &status) {
ucln_i18n_registerCleanup(UCLN_I18N_SMPDTFMT, smpdtfmt_cleanup);
U_ASSERT(gStaticSets == NULL);
gStaticSets = new SimpleDateFormatStaticSets(status);
if (gStaticSets == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
}
U_CDECL_END
UnicodeSet *SimpleDateFormatStaticSets::getIgnorables(UDateFormatField fieldIndex)
{
UErrorCode status = U_ZERO_ERROR;
initSets(&status);
if (U_FAILURE(status)) {
return NULL;
}
UErrorCode status = U_ZERO_ERROR;
umtx_initOnce(gSimpleDateFormatStaticSetsInitOnce, &smpdtfmt_initSets, status);
if (U_FAILURE(status)) {
return NULL;
}
switch (fieldIndex) {
case UDAT_YEAR_FIELD:
@ -152,7 +130,6 @@ UnicodeSet *SimpleDateFormatStaticSets::getIgnorables(UDateFormatField fieldInde
}
}
U_NAMESPACE_END
#endif // #if !UCONFIG_NO_FORMATTING

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2009-2011, International Business Machines Corporation and *
* Copyright (C) 2009-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -28,10 +28,7 @@ class UnicodeSet;
class SimpleDateFormatStaticSets : public UMemory
{
public:
static SimpleDateFormatStaticSets *gStaticSets; // Ptr to all lazily initialized constant
// shared sets.
SimpleDateFormatStaticSets(UErrorCode *status);
SimpleDateFormatStaticSets(UErrorCode &status);
~SimpleDateFormatStaticSets();
static void initSets(UErrorCode *status);

View file

@ -1,6 +1,6 @@
/*
*******************************************************************************
* Copyright (C) 2003-2008, International Business Machines Corporation and *
* Copyright (C) 2003-2013, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*
@ -131,65 +131,21 @@ void TaiwanCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status
}
#endif
// default century
const UDate TaiwanCalendar::fgSystemDefaultCentury = DBL_MIN;
const int32_t TaiwanCalendar::fgSystemDefaultCenturyYear = -1;
UDate TaiwanCalendar::fgSystemDefaultCenturyStart = DBL_MIN;
int32_t TaiwanCalendar::fgSystemDefaultCenturyStartYear = -1;
/**
* The system maintains a static default century start date and Year. They are
* initialized the first time they are used. Once the system default century date
* and year are set, they do not change.
*/
static UDate gSystemDefaultCenturyStart = DBL_MIN;
static int32_t gSystemDefaultCenturyStartYear = -1;
static UInitOnce gSystemDefaultCenturyInit = U_INITONCE_INITIALIZER;
UBool TaiwanCalendar::haveDefaultCentury() const
{
return TRUE;
}
UDate TaiwanCalendar::defaultCenturyStart() const
{
return internalGetDefaultCenturyStart();
}
int32_t TaiwanCalendar::defaultCenturyStartYear() const
{
return internalGetDefaultCenturyStartYear();
}
UDate
TaiwanCalendar::internalGetDefaultCenturyStart() const
{
// lazy-evaluate systemDefaultCenturyStart
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStart
return fgSystemDefaultCenturyStart;
}
int32_t
TaiwanCalendar::internalGetDefaultCenturyStartYear() const
{
// lazy-evaluate systemDefaultCenturyStartYear
UBool needsUpdate;
UMTX_CHECK(NULL, (fgSystemDefaultCenturyStart == fgSystemDefaultCentury), needsUpdate);
if (needsUpdate) {
initializeSystemDefaultCentury();
}
// use defaultCenturyStart unless it's the flag value;
// then use systemDefaultCenturyStartYear
return fgSystemDefaultCenturyStartYear;
}
void
TaiwanCalendar::initializeSystemDefaultCentury()
static void U_CALLCONV initializeSystemDefaultCentury()
{
// initialize systemDefaultCentury and systemDefaultCenturyYear based
// on the current time. They'll be set to 80 years before
@ -200,20 +156,25 @@ TaiwanCalendar::initializeSystemDefaultCentury()
{
calendar.setTime(Calendar::getNow(), status);
calendar.add(UCAL_YEAR, -80, status);
UDate newStart = calendar.getTime(status);
int32_t newYear = calendar.get(UCAL_YEAR, status);
umtx_lock(NULL);
if (fgSystemDefaultCenturyStart == fgSystemDefaultCentury)
{
fgSystemDefaultCenturyStartYear = newYear;
fgSystemDefaultCenturyStart = newStart;
}
umtx_unlock(NULL);
gSystemDefaultCenturyStart = calendar.getTime(status);
gSystemDefaultCenturyStartYear = calendar.get(UCAL_YEAR, status);
}
// We have no recourse upon failure unless we want to propagate the failure
// out.
}
UDate TaiwanCalendar::defaultCenturyStart() const {
// lazy-evaluate systemDefaultCenturyStart
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStart;
}
int32_t TaiwanCalendar::defaultCenturyStartYear() const {
// lazy-evaluate systemDefaultCenturyStartYear
umtx_initOnce(gSystemDefaultCenturyInit, &initializeSystemDefaultCentury);
return gSystemDefaultCenturyStartYear;
}
U_NAMESPACE_END

View file

@ -1,6 +1,6 @@
/*
********************************************************************************
* Copyright (C) 2003-2007, International Business Machines Corporation
* Copyright (C) 2003-2013, International Business Machines Corporation
* and others. All Rights Reserved.
********************************************************************************
*
@ -171,49 +171,6 @@ private:
* @internal
*/
virtual int32_t defaultCenturyStartYear() const;
private: // default century stuff.
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* start of default century, as a date
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates
* with 2-digit years are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with
* 2-digit years are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years
* are considered to fall within so that its start date is 80 years
* before the current time.
*/
static void initializeSystemDefaultCentury(void);
};
U_NAMESPACE_END

View file

@ -39,6 +39,7 @@
#include "unicode/utypes.h"
#include "unicode/ustring.h"
#include "uassert.h"
#include "ustr_imp.h"
#ifdef U_DEBUG_TZ
@ -109,14 +110,15 @@ static const UChar UNKNOWN_ZONE_ID[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x
static const int32_t GMT_ID_LENGTH = 3;
static const int32_t UNKNOWN_ZONE_ID_LENGTH = 11;
static UMutex LOCK = U_MUTEX_INITIALIZER;
static UMutex TZSET_LOCK = U_MUTEX_INITIALIZER;
static icu::TimeZone* DEFAULT_ZONE = NULL;
static UInitOnce gDefaultZoneInitOnce = U_INITONCE_INITIALIZER;
static icu::TimeZone* _GMT = NULL;
static icu::TimeZone* _UNKNOWN_ZONE = NULL;
static UInitOnce gStaticZonesInitOnce = U_INITONCE_INITIALIZER;
static char TZDATA_VERSION[16];
static UBool TZDataVersionInitialized = FALSE;
static UInitOnce gTZDataVersionInitOnce = U_INITONCE_INITIALIZER;
static int32_t* MAP_SYSTEM_ZONES = NULL;
static int32_t* MAP_CANONICAL_SYSTEM_ZONES = NULL;
@ -126,32 +128,41 @@ static int32_t LEN_SYSTEM_ZONES = 0;
static int32_t LEN_CANONICAL_SYSTEM_ZONES = 0;
static int32_t LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
static UInitOnce gSystemZonesInitOnce = U_INITONCE_INITIALIZER;
static UInitOnce gCanonicalZonesInitOnce = U_INITONCE_INITIALIZER;
static UInitOnce gCanonicalLocationZonesInitOnce = U_INITONCE_INITIALIZER;
U_CDECL_BEGIN
static UBool U_CALLCONV timeZone_cleanup(void)
{
U_NAMESPACE_USE
delete DEFAULT_ZONE;
DEFAULT_ZONE = NULL;
gDefaultZoneInitOnce.reset();
delete _GMT;
_GMT = NULL;
delete _UNKNOWN_ZONE;
_UNKNOWN_ZONE = NULL;
gStaticZonesInitOnce.reset();
uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
TZDataVersionInitialized = FALSE;
gTZDataVersionInitOnce.reset();
LEN_SYSTEM_ZONES = 0;
uprv_free(MAP_SYSTEM_ZONES);
MAP_SYSTEM_ZONES = 0;
gSystemZonesInitOnce.reset();
LEN_CANONICAL_SYSTEM_ZONES = 0;
uprv_free(MAP_CANONICAL_SYSTEM_ZONES);
MAP_CANONICAL_SYSTEM_ZONES = 0;
gCanonicalZonesInitOnce.reset();
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
uprv_free(MAP_CANONICAL_SYSTEM_LOCATION_ZONES);
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
gCanonicalLocationZonesInitOnce.reset();
return TRUE;
}
@ -287,31 +298,12 @@ static UResourceBundle* openOlsonResource(const UnicodeString& id,
namespace {
void
ensureStaticTimeZones() {
UBool needsInit;
UMTX_CHECK(&LOCK, (_GMT == NULL), needsInit); /* This is here to prevent race conditions. */
void U_CALLCONV initStaticTimeZones() {
// Initialize _GMT independently of other static data; it should
// be valid even if we can't load the time zone UDataMemory.
if (needsInit) {
SimpleTimeZone *tmpUnknown =
new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
SimpleTimeZone *tmpGMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
umtx_lock(&LOCK);
if (_UNKNOWN_ZONE == 0) {
_UNKNOWN_ZONE = tmpUnknown;
tmpUnknown = NULL;
}
if (_GMT == 0) {
_GMT = tmpGMT;
tmpGMT = NULL;
}
umtx_unlock(&LOCK);
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
delete tmpUnknown;
delete tmpGMT;
}
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
_UNKNOWN_ZONE = new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
_GMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
}
} // anonymous namespace
@ -319,14 +311,14 @@ ensureStaticTimeZones() {
const TimeZone& U_EXPORT2
TimeZone::getUnknown()
{
ensureStaticTimeZones();
umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
return *_UNKNOWN_ZONE;
}
const TimeZone* U_EXPORT2
TimeZone::getGMT(void)
{
ensureStaticTimeZones();
umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
return _GMT;
}
@ -381,43 +373,9 @@ TimeZone::operator==(const TimeZone& that) const
// -------------------------------------
TimeZone* U_EXPORT2
TimeZone::createTimeZone(const UnicodeString& ID)
{
/* We first try to lookup the zone ID in our system list. If this
* fails, we try to parse it as a custom string GMT[+-]hh:mm. If
* all else fails, we return GMT, which is probably not what the
* user wants, but at least is a functioning TimeZone object.
*
* We cannot return NULL, because that would break compatibility
* with the JDK.
*/
TimeZone* result = createSystemTimeZone(ID);
if (result == 0) {
U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
result = createCustomTimeZone(ID);
}
if (result == 0) {
U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
result = getUnknown().clone();
}
return result;
}
/**
* Lookup the given name in our system zone table. If found,
* instantiate a new zone of that name and return it. If not
* found, return 0.
*/
namespace {
TimeZone*
TimeZone::createSystemTimeZone(const UnicodeString& id) {
UErrorCode ec = U_ZERO_ERROR;
return createSystemTimeZone(id, ec);
}
TimeZone*
TimeZone::createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
if (U_FAILURE(ec)) {
return NULL;
}
@ -443,19 +401,60 @@ TimeZone::createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
return z;
}
/**
* Lookup the given name in our system zone table. If found,
* instantiate a new zone of that name and return it. If not
* found, return 0.
*/
TimeZone*
createSystemTimeZone(const UnicodeString& id) {
UErrorCode ec = U_ZERO_ERROR;
return createSystemTimeZone(id, ec);
}
}
TimeZone* U_EXPORT2
TimeZone::createTimeZone(const UnicodeString& ID)
{
/* We first try to lookup the zone ID in our system list. If this
* fails, we try to parse it as a custom string GMT[+-]hh:mm. If
* all else fails, we return GMT, which is probably not what the
* user wants, but at least is a functioning TimeZone object.
*
* We cannot return NULL, because that would break compatibility
* with the JDK.
*/
TimeZone* result = createSystemTimeZone(ID);
if (result == 0) {
U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
result = createCustomTimeZone(ID);
}
if (result == 0) {
U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
result = getUnknown().clone();
}
return result;
}
// -------------------------------------
/**
* Initialize DEFAULT_ZONE from the system default time zone. The
* caller should confirm that DEFAULT_ZONE is NULL before calling.
* Initialize DEFAULT_ZONE from the system default time zone.
* Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
* returns NULL.
*
* Must be called OUTSIDE mutex.
*/
void
TimeZone::initDefault()
static void U_CALLCONV initDefault()
{
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
// If setDefault() has already been called we can skip getting the
// default zone information from the system.
if (DEFAULT_ZONE != NULL) {
return;
}
// We access system timezone data through TPlatformUtilities,
// including tzset(), timezone, and tzname[].
int32_t rawOffset = 0;
@ -463,38 +462,27 @@ TimeZone::initDefault()
// First, try to create a system timezone, based
// on the string ID in tzname[0].
{
// NOTE: Local mutex here. TimeZone mutex below
// mutexed to avoid threading issues in the platform functions.
// Some of the locale/timezone OS functions may not be thread safe,
// so the intent is that any setting from anywhere within ICU
// happens while the ICU mutex is held.
// The operating system might actually use ICU to implement timezones.
// So we may have ICU calling ICU here, like on AIX.
// In order to prevent a double lock of a non-reentrant mutex in a
// different part of ICU, we use TZSET_LOCK to allow only one instance
// of ICU to query these thread unsafe OS functions at any given time.
Mutex lock(&TZSET_LOCK);
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
uprv_tzset(); // Initialize tz... system data
// NOTE: this code is safely single threaded, being only
// run via umtx_initOnce().
//
// Some of the locale/timezone OS functions may not be thread safe,
//
// The operating system might actually use ICU to implement timezones.
// So we may have ICU calling ICU here, like on AIX.
// There shouldn't be a problem with this; initOnce does not hold a mutex
// while the init function is being run.
// Get the timezone ID from the host. This function should do
// any required host-specific remapping; e.g., on Windows this
// function maps the Date and Time control panel setting to an
// ICU timezone ID.
hostID = uprv_tzname(0);
uprv_tzset(); // Initialize tz... system data
// Invert sign because UNIX semantics are backwards
rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
}
// Get the timezone ID from the host. This function should do
// any required host-specific remapping; e.g., on Windows this
// function maps the Date and Time control panel setting to an
// ICU timezone ID.
hostID = uprv_tzname(0);
UBool initialized;
UMTX_CHECK(&LOCK, (DEFAULT_ZONE != NULL), initialized);
if (initialized) {
/* Hrmph? Either a race condition happened, or tzset initialized ICU. */
return;
}
// Invert sign because UNIX semantics are backwards
rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
TimeZone* default_zone = NULL;
@ -527,7 +515,7 @@ TimeZone::initDefault()
// If we _still_ don't have a time zone, use GMT.
if (default_zone == NULL) {
const TimeZone* temptz = getGMT();
const TimeZone* temptz = TimeZone::getGMT();
// If we can't use GMT, get out.
if (temptz == NULL) {
return;
@ -535,16 +523,12 @@ TimeZone::initDefault()
default_zone = temptz->clone();
}
// If DEFAULT_ZONE is still NULL, set it up.
umtx_lock(&LOCK);
if (DEFAULT_ZONE == NULL) {
DEFAULT_ZONE = default_zone;
default_zone = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
}
umtx_unlock(&LOCK);
// The only way for DEFAULT_ZONE to be non-null at this point is if the user
// made a thread-unsafe call to setDefault() or adoptDefault() in another
// thread while this thread was doing something that required getting the default.
U_ASSERT(DEFAULT_ZONE == NULL);
delete default_zone;
DEFAULT_ZONE = default_zone;
}
// -------------------------------------
@ -552,14 +536,7 @@ TimeZone::initDefault()
TimeZone* U_EXPORT2
TimeZone::createDefault()
{
/* This is here to prevent race conditions. */
UBool needsInit;
UMTX_CHECK(&LOCK, (DEFAULT_ZONE == NULL), needsInit);
if (needsInit) {
initDefault();
}
Mutex lock(&LOCK); // In case adoptDefault is called
umtx_initOnce(gDefaultZoneInitOnce, initDefault);
return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
}
@ -570,13 +547,8 @@ TimeZone::adoptDefault(TimeZone* zone)
{
if (zone != NULL)
{
TimeZone* old = NULL;
umtx_lock(&LOCK);
old = DEFAULT_ZONE;
TimeZone *old = DEFAULT_ZONE;
DEFAULT_ZONE = zone;
umtx_unlock(&LOCK);
delete old;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
}
@ -591,6 +563,84 @@ TimeZone::setDefault(const TimeZone& zone)
//----------------------------------------------------------------------
static void U_CALLCONV initMap(USystemTimeZoneType type, UErrorCode& ec) {
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
if (U_SUCCESS(ec)) {
int32_t size = ures_getSize(res);
int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
if (m == NULL) {
ec = U_MEMORY_ALLOCATION_ERROR;
} else {
int32_t numEntries = 0;
for (int32_t i = 0; i < size; i++) {
UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
if (U_FAILURE(ec)) {
break;
}
if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
// exclude Etc/Unknown
continue;
}
if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
UnicodeString canonicalID;
ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
if (U_FAILURE(ec)) {
break;
}
if (canonicalID != id) {
// exclude aliases
continue;
}
}
if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
const UChar *region = TimeZone::getRegion(id, ec);
if (U_FAILURE(ec)) {
break;
}
if (u_strcmp(region, WORLD) == 0) {
// exclude non-location ("001")
continue;
}
}
m[numEntries++] = i;
}
if (U_SUCCESS(ec)) {
int32_t *tmp = m;
m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
if (m == NULL) {
// realloc failed.. use the original one even it has unused
// area at the end
m = tmp;
}
switch(type) {
case UCAL_ZONE_TYPE_ANY:
U_ASSERT(MAP_SYSTEM_ZONES == NULL);
MAP_SYSTEM_ZONES = m;
LEN_SYSTEM_ZONES = numEntries;
break;
case UCAL_ZONE_TYPE_CANONICAL:
U_ASSERT(MAP_CANONICAL_SYSTEM_ZONES == NULL);
MAP_CANONICAL_SYSTEM_ZONES = m;
LEN_CANONICAL_SYSTEM_ZONES = numEntries;
break;
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
U_ASSERT(MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL);
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
break;
}
}
}
}
ures_close(res);
}
/**
* This is the default implementation for subclasses that do not
* override this method. This implementation calls through to the
@ -688,129 +738,29 @@ private:
int32_t* m = NULL;
switch (type) {
case UCAL_ZONE_TYPE_ANY:
umtx_initOnce(gSystemZonesInitOnce, &initMap, type, ec);
m = MAP_SYSTEM_ZONES;
len = LEN_SYSTEM_ZONES;
break;
case UCAL_ZONE_TYPE_CANONICAL:
umtx_initOnce(gCanonicalZonesInitOnce, &initMap, type, ec);
m = MAP_CANONICAL_SYSTEM_ZONES;
len = LEN_CANONICAL_SYSTEM_ZONES;
break;
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
umtx_initOnce(gCanonicalLocationZonesInitOnce, &initMap, type, ec);
m = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
break;
}
UBool needsInit = FALSE;
UMTX_CHECK(&LOCK, (len == 0), needsInit);
if (needsInit) {
m = initMap(type, len, ec);
default:
ec = U_ILLEGAL_ARGUMENT_ERROR;
m = NULL;
len = 0;
break;
}
return m;
}
static int32_t* initMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
len = 0;
if (U_FAILURE(ec)) {
return NULL;
}
int32_t *result = NULL;
UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
if (U_SUCCESS(ec)) {
int32_t size = ures_getSize(res);
int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
if (m == NULL) {
ec = U_MEMORY_ALLOCATION_ERROR;
} else {
int32_t numEntries = 0;
for (int32_t i = 0; i < size; i++) {
UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
if (U_FAILURE(ec)) {
break;
}
if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
// exclude Etc/Unknown
continue;
}
if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
UnicodeString canonicalID;
ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
if (U_FAILURE(ec)) {
break;
}
if (canonicalID != id) {
// exclude aliases
continue;
}
}
if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
const UChar *region = TimeZone::getRegion(id, ec);
if (U_FAILURE(ec)) {
break;
}
if (u_strcmp(region, WORLD) == 0) {
// exclude non-location ("001")
continue;
}
}
m[numEntries++] = i;
}
if (U_SUCCESS(ec)) {
int32_t *tmp = m;
m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
if (m == NULL) {
// realloc failed.. use the original one even it has unused
// area at the end
m = tmp;
}
umtx_lock(&LOCK);
{
switch(type) {
case UCAL_ZONE_TYPE_ANY:
if (MAP_SYSTEM_ZONES == NULL) {
MAP_SYSTEM_ZONES = m;
LEN_SYSTEM_ZONES = numEntries;
m = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
}
result = MAP_SYSTEM_ZONES;
len = LEN_SYSTEM_ZONES;
break;
case UCAL_ZONE_TYPE_CANONICAL:
if (MAP_CANONICAL_SYSTEM_ZONES == NULL) {
MAP_CANONICAL_SYSTEM_ZONES = m;
LEN_CANONICAL_SYSTEM_ZONES = numEntries;
m = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
}
result = MAP_CANONICAL_SYSTEM_ZONES;
len = LEN_CANONICAL_SYSTEM_ZONES;
break;
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
if (MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL) {
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
m = NULL;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
}
result = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
break;
}
}
umtx_unlock(&LOCK);
}
uprv_free(m);
}
}
ures_close(res);
return result;
}
public:
#define DEFAULT_FILTERED_MAP_SIZE 8
@ -866,7 +816,7 @@ public:
if (rawOffset != NULL) {
// Filter by raw offset
// Note: This is VERY inefficient
TimeZone *z = TimeZone::createSystemTimeZone(id, ec);
TimeZone *z = createSystemTimeZone(id, ec);
if (U_FAILURE(ec)) {
break;
}
@ -1516,37 +1466,27 @@ TimeZone::hasSameRules(const TimeZone& other) const
useDaylightTime() == other.useDaylightTime());
}
static void U_CALLCONV initTZDataVersion(UErrorCode &status) {
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
int32_t len = 0;
UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION, &len, &status);
if (U_SUCCESS(status)) {
if (len >= (int32_t)sizeof(TZDATA_VERSION)) {
// Ensure that there is always space for a trailing nul in TZDATA_VERSION
len = sizeof(TZDATA_VERSION) - 1;
}
u_UCharsToChars(tzver, TZDATA_VERSION, len);
}
ures_close(bundle);
}
const char*
TimeZone::getTZDataVersion(UErrorCode& status)
{
/* This is here to prevent race conditions. */
UBool needsInit;
UMTX_CHECK(&LOCK, !TZDataVersionInitialized, needsInit);
if (needsInit) {
int32_t len = 0;
UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION,
&len, &status);
if (U_SUCCESS(status)) {
if (len >= (int32_t)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);
}
ures_close(bundle);
}
if (U_FAILURE(status)) {
return NULL;
}
umtx_initOnce(gTZDataVersionInitOnce, &initTZDataVersion, status);
return (const char*)TZDATA_VERSION;
}

View file

@ -136,10 +136,10 @@ static const int32_t ALL_GENERIC_NAME_TYPES = UTZGNM_LOCATION | UTZGNM_LONG | UT
// Time Zone ID/Short ID trie
static TextTrieMap *gZoneIdTrie = NULL;
static UBool gZoneIdTrieInitialized = FALSE;
static UInitOnce gZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
static TextTrieMap *gShortZoneIdTrie = NULL;
static UBool gShortZoneIdTrieInitialized = FALSE;
static UInitOnce gShortZoneIdTrieInitOnce = U_INITONCE_INITIALIZER;
static UMutex gLock = U_MUTEX_INITIALIZER;
@ -153,13 +153,13 @@ static UBool U_CALLCONV tzfmt_cleanup(void)
delete gZoneIdTrie;
}
gZoneIdTrie = NULL;
gZoneIdTrieInitialized = FALSE;
gZoneIdTrieInitOnce.reset();
if (gShortZoneIdTrie != NULL) {
delete gShortZoneIdTrie;
}
gShortZoneIdTrie = NULL;
gShortZoneIdTrieInitialized = FALSE;
gShortZoneIdTrieInitOnce.reset();
return TRUE;
}
@ -438,6 +438,7 @@ TimeZoneFormat::operator=(const TimeZoneFormat& other) {
fTimeZoneNames = other.fTimeZoneNames->clone();
if (other.fTimeZoneGenericNames) {
// TODO: this test has dubious thread safety.
fTimeZoneGenericNames = other.fTimeZoneGenericNames->clone();
}
@ -1291,18 +1292,12 @@ TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
return NULL;
}
UBool create;
UMTX_CHECK(&gZoneMetaLock, (fTimeZoneGenericNames == NULL), create);
if (create) {
umtx_lock(&gLock);
if (fTimeZoneGenericNames == NULL) {
TimeZoneFormat *nonConstThis = const_cast<TimeZoneFormat *>(this);
umtx_lock(&gLock);
{
if (fTimeZoneGenericNames == NULL) {
nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status);
}
}
umtx_unlock(&gLock);
nonConstThis->fTimeZoneGenericNames = TimeZoneGenericNames::createInstance(fLocale, status);
}
umtx_unlock(&gLock);
return fTimeZoneGenericNames;
}
@ -2634,44 +2629,37 @@ ZoneIdMatchHandler::getMatchLen() {
return fLen;
}
static void U_CALLCONV initZoneIdTrie(UErrorCode &status) {
U_ASSERT(gZoneIdTrie == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
gZoneIdTrie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
if (gZoneIdTrie == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
StringEnumeration *tzenum = TimeZone::createEnumeration();
const UnicodeString *id;
while ((id = tzenum->snext(status))) {
const UChar* uid = ZoneMeta::findTimeZoneID(*id);
if (uid) {
gZoneIdTrie->put(uid, const_cast<UChar *>(uid), status);
}
}
delete tzenum;
}
UnicodeString&
TimeZoneFormat::parseZoneID(const UnicodeString& text, ParsePosition& pos, UnicodeString& tzID) const {
UErrorCode status = U_ZERO_ERROR;
UBool initialized;
UMTX_CHECK(&gLock, gZoneIdTrieInitialized, initialized);
if (!initialized) {
umtx_lock(&gLock);
{
if (!gZoneIdTrieInitialized) {
StringEnumeration *tzenum = TimeZone::createEnumeration();
TextTrieMap* trie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
if (trie) {
const UnicodeString *id;
while ((id = tzenum->snext(status))) {
const UChar* uid = ZoneMeta::findTimeZoneID(*id);
if (uid) {
trie->put(uid, const_cast<UChar *>(uid), status);
}
}
if (U_SUCCESS(status)) {
gZoneIdTrie = trie;
gZoneIdTrieInitialized = initialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
} else {
delete trie;
}
}
delete tzenum;
}
}
umtx_unlock(&gLock);
}
umtx_initOnce(gZoneIdTrieInitOnce, &initZoneIdTrie, status);
int32_t start = pos.getIndex();
int32_t len = 0;
tzID.setToBogus();
if (initialized) {
if (U_SUCCESS(status)) {
LocalPointer<ZoneIdMatchHandler> handler(new ZoneIdMatchHandler());
gZoneIdTrie->search(text, start, handler.getAlias(), status);
len = handler->getMatchLen();
@ -2689,47 +2677,39 @@ TimeZoneFormat::parseZoneID(const UnicodeString& text, ParsePosition& pos, Unico
return tzID;
}
static void U_CALLCONV initShortZoneIdTrie(UErrorCode &status) {
U_ASSERT(gShortZoneIdTrie == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
StringEnumeration *tzenum = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
if (U_SUCCESS(status)) {
gShortZoneIdTrie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
if (gShortZoneIdTrie == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
} else {
const UnicodeString *id;
while ((id = tzenum->snext(status))) {
const UChar* uID = ZoneMeta::findTimeZoneID(*id);
const UChar* shortID = ZoneMeta::getShortID(*id);
if (shortID && uID) {
gShortZoneIdTrie->put(shortID, const_cast<UChar *>(uID), status);
}
}
}
}
delete tzenum;
}
UnicodeString&
TimeZoneFormat::parseShortZoneID(const UnicodeString& text, ParsePosition& pos, UnicodeString& tzID) const {
UErrorCode status = U_ZERO_ERROR;
UBool initialized;
UMTX_CHECK(&gLock, gShortZoneIdTrieInitialized, initialized);
if (!initialized) {
umtx_lock(&gLock);
{
if (!gShortZoneIdTrieInitialized) {
StringEnumeration *tzenum = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, status);
if (U_SUCCESS(status)) {
TextTrieMap* trie = new TextTrieMap(TRUE, NULL); // No deleter, because values are pooled by ZoneMeta
if (trie) {
const UnicodeString *id;
while ((id = tzenum->snext(status))) {
const UChar* uID = ZoneMeta::findTimeZoneID(*id);
const UChar* shortID = ZoneMeta::getShortID(*id);
if (shortID && uID) {
trie->put(shortID, const_cast<UChar *>(uID), status);
}
}
if (U_SUCCESS(status)) {
gShortZoneIdTrie = trie;
gShortZoneIdTrieInitialized = initialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONEFORMAT, tzfmt_cleanup);
} else {
delete trie;
}
}
}
delete tzenum;
}
}
umtx_unlock(&gLock);
}
umtx_initOnce(gShortZoneIdTrieInitOnce, &initShortZoneIdTrie, status);
int32_t start = pos.getIndex();
int32_t len = 0;
tzID.setToBogus();
if (initialized) {
if (U_SUCCESS(status)) {
LocalPointer<ZoneIdMatchHandler> handler(new ZoneIdMatchHandler());
gShortZoneIdTrie->search(text, start, handler.getAlias(), status);
len = handler->getMatchLen();

View file

@ -20,6 +20,7 @@
#include "cmemory.h"
#include "cstring.h"
#include "mutex.h"
#include "uhash.h"
#include "uassert.h"
#include "umutex.h"
@ -1222,33 +1223,25 @@ TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) {
return NULL;
}
UBool initialized;
UMTX_CHECK(&gTZGNLock, gTZGNCoreCacheInitialized, initialized);
if (!initialized) {
// Create empty hashtable
umtx_lock(&gTZGNLock);
{
if (!gTZGNCoreCacheInitialized) {
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);
}
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);
}
}
umtx_unlock(&gTZGNLock);
if (U_FAILURE(status)) {
return NULL;
}
}
// Check the cache, if not available, create new one and cache
TZGNCoreRef *cacheEntry = NULL;
umtx_lock(&gTZGNLock);
{
// 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) {
@ -1302,8 +1295,7 @@ TimeZoneGenericNames::createInstance(const Locale& locale, UErrorCode& status) {
sweepCache();
gAccessCount = 0;
}
}
umtx_unlock(&gTZGNLock);
} // End of mutex locked block
if (cacheEntry == NULL) {
delete instance;

View file

@ -14,6 +14,7 @@
#include "unicode/uenum.h"
#include "cmemory.h"
#include "cstring.h"
#include "mutex.h"
#include "putilimp.h"
#include "tznames_impl.h"
#include "uassert.h"
@ -126,89 +127,78 @@ TimeZoneNamesDelegate::TimeZoneNamesDelegate()
}
TimeZoneNamesDelegate::TimeZoneNamesDelegate(const Locale& locale, UErrorCode& status) {
UBool initialized;
UMTX_CHECK(&gTimeZoneNamesLock, gTimeZoneNamesCacheInitialized, initialized);
if (!initialized) {
// Create empty hashtable
umtx_lock(&gTimeZoneNamesLock);
{
if (!gTimeZoneNamesCacheInitialized) {
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);
}
}
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);
}
umtx_unlock(&gTimeZoneNamesLock);
}
if (U_FAILURE(status)) {
return;
}
if (U_FAILURE(status)) {
return;
}
// Check the cache, if not available, create new one and cache
TimeZoneNamesCacheEntry *cacheEntry = NULL;
umtx_lock(&gTimeZoneNamesLock);
{
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) {
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)) {
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();
}
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);
}
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;
}
if (U_FAILURE(status)) {
if (tznames != NULL) {
delete tznames;
}
} else {
// Update the reference count
cacheEntry->refCount++;
cacheEntry->lastAccess = (double)uprv_getUTCtime();
}
gAccessCount++;
if (gAccessCount >= SWEEP_INTERVAL) {
// sweep
sweepCache();
gAccessCount = 0;
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;
}
umtx_unlock(&gTimeZoneNamesLock);
fTZnamesCacheEntry = cacheEntry;
}

View file

@ -20,6 +20,7 @@
#include "cmemory.h"
#include "cstring.h"
#include "uassert.h"
#include "mutex.h"
#include "uresimp.h"
#include "ureslocs.h"
#include "zonemeta.h"
@ -290,7 +291,6 @@ static UMutex TextTrieMutex = U_MUTEX_INITIALIZER;
// needed for parsing operations, which are less common than formatting,
// and the Trie is big, which is why its creation is deferred until first use.
void TextTrieMap::buildTrie(UErrorCode &status) {
umtx_lock(&TextTrieMutex);
if (fLazyContents != NULL) {
for (int32_t i=0; i<fLazyContents->size(); i+=2) {
const UChar *key = (UChar *)fLazyContents->elementAt(i);
@ -301,17 +301,22 @@ void TextTrieMap::buildTrie(UErrorCode &status) {
delete fLazyContents;
fLazyContents = NULL;
}
umtx_unlock(&TextTrieMutex);
}
void
TextTrieMap::search(const UnicodeString &text, int32_t start,
TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
UBool trieNeedsInitialization = FALSE;
UMTX_CHECK(&TextTrieMutex, fLazyContents != NULL, trieNeedsInitialization);
if (trieNeedsInitialization) {
TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
nonConstThis->buildTrie(status);
{
// TODO: if locking the mutex for each check proves to be a performance problem,
// add a flag of type atomic_int32_t to class TextTrieMap, and use only
// the ICU atomic safe functions for assigning and testing.
// Don't test the pointer fLazyContents.
// Don't do unless it's really required.
Mutex lock(&TextTrieMutex);
if (fLazyContents != NULL) {
TextTrieMap *nonConstThis = const_cast<TextTrieMap *>(this);
nonConstThis->buildTrie(status);
}
}
if (fNodes == NULL) {
return;

View file

@ -29,6 +29,7 @@
#include "unicode/ustring.h"
#include "unicode/utf16.h"
#include "normalizer2impl.h"
#include "uassert.h"
#include "ucol_bld.h"
#include "ucol_elm.h"
#include "ucol_cnt.h"
@ -41,6 +42,7 @@
static const InverseUCATableHeader* _staticInvUCA = NULL;
static UDataMemory* invUCA_DATA_MEM = NULL;
static UInitOnce gStaticInvUCAInitOnce = U_INITONCE_INITIALIZER;
U_CDECL_BEGIN
static UBool U_CALLCONV
@ -1330,61 +1332,48 @@ ucol_bld_cleanup(void)
udata_close(invUCA_DATA_MEM);
invUCA_DATA_MEM = NULL;
_staticInvUCA = NULL;
gStaticInvUCAInitOnce.reset();
return TRUE;
}
U_CDECL_END
static void U_CALLCONV initInverseUCA(UErrorCode &status) {
U_ASSERT(invUCA_DATA_MEM == NULL);
U_ASSERT(_staticInvUCA == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_BLD, ucol_bld_cleanup);
InverseUCATableHeader *newInvUCA = NULL;
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, INVC_DATA_TYPE, INVC_DATA_NAME, isAcceptableInvUCA, NULL, &status);
if(U_FAILURE(status)) {
if (result) {
udata_close(result);
}
// This is not needed, as we are talking about
// memory we got from UData
//uprv_free(newInvUCA);
return;
}
if(result != NULL) { /* It looks like sometimes we can fail to find the data file */
newInvUCA = (InverseUCATableHeader *)udata_getMemory(result);
UCollator *UCA = ucol_initUCA(&status);
// UCA versions of UCA and inverse UCA should match
if(uprv_memcmp(newInvUCA->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0) {
status = U_INVALID_FORMAT_ERROR;
udata_close(result);
return;
}
invUCA_DATA_MEM = result;
_staticInvUCA = newInvUCA;
}
}
U_CAPI const InverseUCATableHeader * U_EXPORT2
ucol_initInverseUCA(UErrorCode *status)
{
if(U_FAILURE(*status)) return NULL;
UBool needsInit;
UMTX_CHECK(NULL, (_staticInvUCA == NULL), needsInit);
if(needsInit) {
InverseUCATableHeader *newInvUCA = NULL;
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, INVC_DATA_TYPE, INVC_DATA_NAME, isAcceptableInvUCA, NULL, status);
if(U_FAILURE(*status)) {
if (result) {
udata_close(result);
}
// This is not needed, as we are talking about
// memory we got from UData
//uprv_free(newInvUCA);
}
if(result != NULL) { /* It looks like sometimes we can fail to find the data file */
newInvUCA = (InverseUCATableHeader *)udata_getMemory(result);
UCollator *UCA = ucol_initUCA(status);
// UCA versions of UCA and inverse UCA should match
if(uprv_memcmp(newInvUCA->UCAVersion, UCA->image->UCAVersion, sizeof(UVersionInfo)) != 0) {
*status = U_INVALID_FORMAT_ERROR;
udata_close(result);
return NULL;
}
umtx_lock(NULL);
if(_staticInvUCA == NULL) {
invUCA_DATA_MEM = result;
_staticInvUCA = newInvUCA;
result = NULL;
newInvUCA = NULL;
}
umtx_unlock(NULL);
if(newInvUCA != NULL) {
udata_close(result);
// This is not needed, as we are talking about
// memory we got from UData
//uprv_free(newInvUCA);
}
else {
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_BLD, ucol_bld_cleanup);
}
}
}
umtx_initOnce(gStaticInvUCAInitOnce, &initInverseUCA, *status);
return _staticInvUCA;
}

View file

@ -44,6 +44,7 @@
#include "putilimp.h"
#include "utracimp.h"
#include "cmemory.h"
#include "uassert.h"
#include "uenumimp.h"
#include "ulist.h"
@ -54,6 +55,7 @@ static void ucol_setReorderCodesFromParser(UCollator *coll, UColTokenParser *par
// static UCA. There is only one. Collators don't use it.
// It is referenced only in ucol_initUCA and ucol_cleanup
static UCollator* _staticUCA = NULL;
static UInitOnce gStaticUCAInitOnce = U_INITONCE_INITIALIZER;
// static pointer to udata memory. Inited in ucol_initUCA
// used for cleanup in ucol_cleanup
static UDataMemory* UCA_DATA_MEM = NULL;
@ -70,6 +72,7 @@ ucol_res_cleanup(void)
ucol_close(_staticUCA);
_staticUCA = NULL;
}
gStaticUCAInitOnce.reset();
return TRUE;
}
@ -106,47 +109,35 @@ isAcceptableUCA(void * /*context*/,
}
U_CDECL_END
static void U_CALLCONV ucol_initStaticUCA(UErrorCode &status) {
U_ASSERT(_staticUCA == NULL);
U_ASSERT(UCA_DATA_MEM == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup);
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, UCA_DATA_TYPE, UCA_DATA_NAME, isAcceptableUCA, NULL, &status);
if(U_FAILURE(status)){
udata_close(result);
return;
}
_staticUCA = ucol_initCollator((const UCATableHeader *)udata_getMemory(result), NULL, NULL, &status);
if(U_SUCCESS(status)){
// Initalize variables for implicit generation
uprv_uca_initImplicitConstants(&status);
UCA_DATA_MEM = result;
}else{
ucol_close(_staticUCA);
_staticUCA = NULL;
udata_close(result);
}
}
/* do not close UCA returned by ucol_initUCA! */
UCollator *
ucol_initUCA(UErrorCode *status) {
if(U_FAILURE(*status)) {
return NULL;
}
UBool needsInit;
UMTX_CHECK(NULL, (_staticUCA == NULL), needsInit);
if(needsInit) {
UDataMemory *result = udata_openChoice(U_ICUDATA_COLL, UCA_DATA_TYPE, UCA_DATA_NAME, isAcceptableUCA, NULL, status);
if(U_SUCCESS(*status)){
UCollator *newUCA = ucol_initCollator((const UCATableHeader *)udata_getMemory(result), NULL, NULL, status);
if(U_SUCCESS(*status)){
// Initalize variables for implicit generation
uprv_uca_initImplicitConstants(status);
umtx_lock(NULL);
if(_staticUCA == NULL) {
UCA_DATA_MEM = result;
_staticUCA = newUCA;
newUCA = NULL;
result = NULL;
}
umtx_unlock(NULL);
ucln_i18n_registerCleanup(UCLN_I18N_UCOL_RES, ucol_res_cleanup);
if(newUCA != NULL) {
ucol_close(newUCA);
udata_close(result);
}
}else{
ucol_close(newUCA);
udata_close(result);
}
}
else {
udata_close(result);
}
}
umtx_initOnce(gStaticUCAInitOnce, &ucol_initStaticUCA, *status);
return _staticUCA;
}
@ -155,6 +146,7 @@ ucol_forgetUCA(void)
{
_staticUCA = NULL;
UCA_DATA_MEM = NULL;
gStaticUCAInitOnce.reset();
}
/****************************************************************************/

View file

@ -99,10 +99,8 @@ static const UChar CHOICE_FORMAT_MARK = 0x003D; // Equals sign
static const UChar EUR_STR[] = {0x0045,0x0055,0x0052,0};
// ISO codes mapping table
static UHashtable* gIsoCodes = NULL;
static UBool gIsoCodesInitialized = FALSE;
static UMutex gIsoCodesLock = U_MUTEX_INITIALIZER;
static const UHashtable* gIsoCodes = NULL;
static UInitOnce gIsoCodesInitOnce = U_INITONCE_INITIALIZER;
//------------------------------------------------------------
// Code
@ -114,11 +112,10 @@ static UBool U_CALLCONV
isoCodes_cleanup(void)
{
if (gIsoCodes != NULL) {
uhash_close(gIsoCodes);
uhash_close(const_cast<UHashtable *>(gIsoCodes));
gIsoCodes = NULL;
}
gIsoCodesInitialized = FALSE;
gIsoCodesInitOnce.reset();
return TRUE;
}
@ -1227,6 +1224,8 @@ static CurrencyNameCacheEntry* currCache[CURRENCY_NAME_CACHE_NUM] = {NULL};
// It is a simple round-robin replacement strategy.
static int8_t currentCacheEntryIndex = 0;
static UMutex gCurrencyCacheMutex = U_MUTEX_INITIALIZER;
// Cache deletion
static void
deleteCurrencyNames(CurrencyNameStruct* currencyNames, int32_t count) {
@ -1280,9 +1279,9 @@ uprv_parseCurrency(const char* locale,
CurrencyNameStruct* currencySymbols = NULL;
CurrencyNameCacheEntry* cacheEntry = NULL;
umtx_lock(NULL);
umtx_lock(&gCurrencyCacheMutex);
// in order to handle racing correctly,
// not putting 'search' in a separate function and using UMTX.
// not putting 'search' in a separate function.
int8_t found = -1;
for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
if (currCache[i]!= NULL &&
@ -1299,13 +1298,13 @@ uprv_parseCurrency(const char* locale,
total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
++(cacheEntry->refCount);
}
umtx_unlock(NULL);
umtx_unlock(&gCurrencyCacheMutex);
if (found == -1) {
collectCurrencyNames(locale, &currencyNames, &total_currency_name_count, &currencySymbols, &total_currency_symbol_count, ec);
if (U_FAILURE(ec)) {
return;
}
umtx_lock(NULL);
umtx_lock(&gCurrencyCacheMutex);
// check again.
int8_t found = -1;
for (int8_t i = 0; i < CURRENCY_NAME_CACHE_NUM; ++i) {
@ -1350,7 +1349,7 @@ uprv_parseCurrency(const char* locale,
total_currency_symbol_count = cacheEntry->totalCurrencySymbolCount;
++(cacheEntry->refCount);
}
umtx_unlock(NULL);
umtx_unlock(&gCurrencyCacheMutex);
}
int32_t start = pos.getIndex();
@ -1394,12 +1393,12 @@ uprv_parseCurrency(const char* locale,
}
// decrease reference count
umtx_lock(NULL);
umtx_lock(&gCurrencyCacheMutex);
--(cacheEntry->refCount);
if (cacheEntry->refCount == 0) { // remove
deleteCacheEntry(cacheEntry);
}
umtx_unlock(NULL);
umtx_unlock(&gCurrencyCacheMutex);
}
@ -1842,7 +1841,7 @@ ucurr_closeCurrencyList(UEnumeration *enumerator) {
}
static void U_CALLCONV
ucurr_createCurrencyList(UErrorCode* status){
ucurr_createCurrencyList(UHashtable *isoCodes, UErrorCode* status){
UErrorCode localStatus = U_ZERO_ERROR;
// Look up the CurrencyMap element in the root bundle.
@ -1908,7 +1907,7 @@ ucurr_createCurrencyList(UErrorCode* status){
entry->to = toDate;
localStatus = U_ZERO_ERROR;
uhash_put(gIsoCodes, (UChar *)isoCode, entry, &localStatus);
uhash_put(isoCodes, (UChar *)isoCode, entry, &localStatus);
}
} else {
*status = localStatus;
@ -1933,36 +1932,35 @@ static const UEnumeration gEnumCurrencyList = {
};
U_CDECL_END
static void U_CALLCONV initIsoCodes(UErrorCode &status) {
U_ASSERT(gIsoCodes == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
UHashtable *isoCodes = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
if (U_FAILURE(status)) {
return;
}
uhash_setValueDeleter(isoCodes, deleteIsoCodeEntry);
ucurr_createCurrencyList(isoCodes, &status);
if (U_FAILURE(status)) {
uhash_close(isoCodes);
return;
}
gIsoCodes = isoCodes; // Note: gIsoCodes is const. Once set up here it is never altered,
// and read only access is safe without synchronization.
}
U_CAPI UBool U_EXPORT2
ucurr_isAvailable(const UChar* isoCode, UDate from, UDate to, UErrorCode* eErrorCode) {
UErrorCode status = U_ZERO_ERROR;
UBool initialized;
UMTX_CHECK(&gIsoCodesLock, gIsoCodesInitialized, initialized);
if (!initialized) {
umtx_lock(&gIsoCodesLock);
gIsoCodes = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
if (U_FAILURE(status)) {
umtx_unlock(&gIsoCodesLock);
return FALSE;
}
uhash_setValueDeleter(gIsoCodes, deleteIsoCodeEntry);
ucln_i18n_registerCleanup(UCLN_I18N_CURRENCY, currency_cleanup);
ucurr_createCurrencyList(&status);
if (U_FAILURE(status)) {
umtx_unlock(&gIsoCodesLock);
return FALSE;
}
gIsoCodesInitialized = TRUE;
umtx_unlock(&gIsoCodesLock);
umtx_initOnce(gIsoCodesInitOnce, &initIsoCodes, *eErrorCode);
if (U_FAILURE(*eErrorCode)) {
return FALSE;
}
umtx_lock(&gIsoCodesLock);
IsoCodeEntry* result = (IsoCodeEntry *) uhash_get(gIsoCodes, isoCode);
umtx_unlock(&gIsoCodesLock);
if (result == NULL) {
return FALSE;
} else if (from > to) {
@ -1971,7 +1969,6 @@ ucurr_isAvailable(const UChar* isoCode, UDate from, UDate to, UErrorCode* eError
} else if ((from > result->to) || (to < result->from)) {
return FALSE;
}
return TRUE;
}

View file

@ -59,6 +59,7 @@ class CurrencyPluralInfo;
class Hashtable;
class UnicodeSet;
class FieldPositionHandler;
class DecimalFormatStaticSets;
// explicit template instantiation. see digitlst.h
#if defined (_MSC_VER)
@ -1882,15 +1883,15 @@ private:
int32_t precision() const;
/**
* Initialize all fields of a new DecimalFormatter.
* Initialize all fields of a new DecimalFormatter to a safe default value.
* Common code for use by constructors.
*/
void init(UErrorCode& status);
void init();
/**
* Do real work of constructing a new DecimalFormat.
*/
void construct(UErrorCode& status,
void construct(UErrorCode& status,
UParseError& parseErr,
const UnicodeString* pattern = 0,
DecimalFormatSymbols* symbolsToAdopt = 0
@ -2295,6 +2296,9 @@ private:
UNumberFormatAttributeValue fParseAllInput;
#endif
// Decimal Format Static Sets singleton.
const DecimalFormatStaticSets *fStaticSets;
protected:

View file

@ -29,6 +29,9 @@ class GenderInfoTest;
U_NAMESPACE_BEGIN
// Forward Declaration
void GenderInfo_initCache(UErrorCode &status);
/**
* GenderInfo computes the gender of a list as a whole given the gender of
* each element.
@ -96,7 +99,9 @@ private:
static const GenderInfo* getMaleTaintsInstance();
static const GenderInfo* loadInstance(const Locale& locale, UErrorCode& status);
friend class ::GenderInfoTest;
friend void GenderInfo_initCache(UErrorCode &status);
};
U_NAMESPACE_END

View file

@ -767,53 +767,6 @@ public:
* @return the beginning year of the default century
*/
virtual int32_t defaultCenturyStartYear() const;
private:
/**
* The system maintains a static default century start date. This is initialized
* the first time it is used. Before then, it is set to SYSTEM_DEFAULT_CENTURY to
* indicate an uninitialized state. Once the system default century date and year
* are set, they do not change.
*/
static UDate fgSystemDefaultCenturyStart;
/**
* See documentation for systemDefaultCenturyStart.
*/
static int32_t fgSystemDefaultCenturyStartYear;
/**
* Default value that indicates the defaultCenturyStartYear is unitialized
*/
static const int32_t fgSystemDefaultCenturyYear;
/**
* Default value that indicates the UDate of the beginning of the system default century
*/
static const UDate fgSystemDefaultCentury;
/**
* Returns the beginning date of the 100-year window that dates with 2-digit years
* are considered to fall within.
* @return the beginning date of the 100-year window that dates with 2-digit years
* are considered to fall within.
*/
UDate internalGetDefaultCenturyStart(void) const;
/**
* Returns the first year of the 100-year window that dates with 2-digit years
* are considered to fall within.
* @return the first year of the 100-year window that dates with 2-digit years
* are considered to fall within.
*/
int32_t internalGetDefaultCenturyStartYear(void) const;
/**
* Initializes the 100-year window that dates with 2-digit years are considered
* to fall within so that its start date is 80 years before the current time.
*/
static void initializeSystemDefaultCentury(void);
};
U_NAMESPACE_END

View file

@ -291,7 +291,11 @@ public:
* Sets the default time zone (i.e., what's returned by createDefault()) to be the
* specified time zone. If NULL is specified for the time zone, the default time
* zone is set to the default host time zone. This call adopts the TimeZone object
* passed in; the clent is no longer responsible for deleting it.
* passed in; the client is no longer responsible for deleting it.
*
* <p>This function is not thread safe. It is an error for multiple threads
* to concurrently attempt to set the default time zone, or for any thread
* to attempt to reference the default zone while another thread is setting it.
*
* @param zone A pointer to the new TimeZone object to use as the default.
* @stable ICU 2.0
@ -303,6 +307,8 @@ public:
* Same as adoptDefault(), except that the TimeZone object passed in is NOT adopted;
* the caller remains responsible for deleting it.
*
* <p>See the thread safety note under adoptDefault().
*
* @param zone The given timezone.
* @system
* @stable ICU 2.0
@ -863,15 +869,18 @@ private:
*/
static const UChar* getRegion(const UnicodeString& id);
public:
/**
* Returns the region code associated with the given zone,
* or NULL if the zone is not known.
* @param id zone id string
* @param status Status parameter
* @return the region associated with the given zone
* @internal
*/
static const UChar* getRegion(const UnicodeString& id, UErrorCode& status);
private:
/**
* Parses the given custom time zone identifier
* @param id id A string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
@ -910,24 +919,6 @@ private:
static UnicodeString& formatCustomID(int32_t hour, int32_t min, int32_t sec,
UBool negative, UnicodeString& id);
/**
* Responsible for setting up DEFAULT_ZONE. Uses routines in TPlatformUtilities
* (i.e., platform-specific calls) to get the current system time zone. Failing
* that, uses the platform-specific default time zone. Failing that, uses GMT.
*/
static void initDefault(void);
// See source file for documentation
/**
* Lookup the given name in our system zone table. If found,
* instantiate a new zone of that name and return it. If not
* found, return 0.
* @param name tthe given name of a system time zone.
* @return the TimeZone indicated by the 'name'.
*/
static TimeZone* createSystemTimeZone(const UnicodeString& name);
static TimeZone* createSystemTimeZone(const UnicodeString& name, UErrorCode& ec);
UnicodeString fID; // this time zone's ID
friend class TZEnumeration;

View file

@ -1,9 +1,9 @@
/*
*******************************************************************************
* Copyright (C) 2004-2012, International Business Machines
* Copyright (C) 2004-2013, International Business Machines
* Corporation and others. All Rights Reserved.
*******************************************************************************
* file name: regex.cpp
* file name: uregex.cpp
*/
#include "unicode/utypes.h"
@ -35,7 +35,7 @@ public:
~RegularExpression();
int32_t fMagic;
RegexPattern *fPat;
int32_t *fPatRefCount;
atomic_int32_t *fPatRefCount;
UChar *fPatString;
int32_t fPatStringLen;
RegexMatcher *fMatcher;
@ -65,7 +65,7 @@ RegularExpression::~RegularExpression() {
if (fPatRefCount!=NULL && umtx_atomic_dec(fPatRefCount)==0) {
delete fPat;
uprv_free(fPatString);
uprv_free(fPatRefCount);
uprv_free((void *)fPatRefCount);
}
if (fOwnsText && fText!=NULL) {
uprv_free((void *)fText);
@ -122,13 +122,13 @@ uregex_open( const UChar *pattern,
actualPatLen = u_strlen(pattern);
}
RegularExpression *re = new RegularExpression;
int32_t *refC = (int32_t *)uprv_malloc(sizeof(int32_t));
RegularExpression *re = new RegularExpression;
atomic_int32_t *refC = (atomic_int32_t *)uprv_malloc(sizeof(int32_t));
UChar *patBuf = (UChar *)uprv_malloc(sizeof(UChar)*(actualPatLen+1));
if (re == NULL || refC == NULL || patBuf == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
delete re;
uprv_free(refC);
uprv_free((void *)refC);
uprv_free(patBuf);
return NULL;
}
@ -207,12 +207,12 @@ uregex_openUText(UText *pattern,
UErrorCode lengthStatus = U_ZERO_ERROR;
int32_t pattern16Length = utext_extract(pattern, 0, patternNativeLength, NULL, 0, &lengthStatus);
int32_t *refC = (int32_t *)uprv_malloc(sizeof(int32_t));
atomic_int32_t *refC = (atomic_int32_t *)uprv_malloc(sizeof(int32_t));
UChar *patBuf = (UChar *)uprv_malloc(sizeof(UChar)*(pattern16Length+1));
if (re == NULL || refC == NULL || patBuf == NULL) {
*status = U_MEMORY_ALLOCATION_ERROR;
delete re;
uprv_free(refC);
uprv_free((void *)refC);
uprv_free(patBuf);
return NULL;
}

View file

@ -242,7 +242,7 @@ class SpoofData: public UMemory {
// we are done.
uint32_t fMemLimit; // Limit of available raw data space
int32_t fRefCount;
atomic_int32_t fRefCount;
// Confusable data
int32_t *fCFUKeys;

View file

@ -31,21 +31,21 @@ static UMutex gZoneMetaLock = U_MUTEX_INITIALIZER;
// CLDR Canonical ID mapping table
static UHashtable *gCanonicalIDCache = NULL;
static UBool gCanonicalIDCacheInitialized = FALSE;
static UInitOnce gCanonicalIDCacheInitOnce = U_INITONCE_INITIALIZER;
// Metazone mapping table
static UHashtable *gOlsonToMeta = NULL;
static UBool gOlsonToMetaInitialized = FALSE;
static UInitOnce gOlsonToMetaInitOnce = U_INITONCE_INITIALIZER;
// Available metazone IDs vector and table
static icu::UVector *gMetaZoneIDs = NULL;
static UHashtable *gMetaZoneIDTable = NULL;
static UBool gMetaZoneIDsInitialized = FALSE;
static UInitOnce gMetaZoneIDsInitOnce = U_INITONCE_INITIALIZER;
// Country info vectors
static icu::UVector *gSingleZoneCountries = NULL;
static icu::UVector *gMultiZonesCountries = NULL;
static UBool gCountryInfoVectorsInitialized = FALSE;
static UInitOnce gCountryInfoVectorsInitOnce = U_INITONCE_INITIALIZER;
U_CDECL_BEGIN
@ -58,25 +58,29 @@ static UBool U_CALLCONV zoneMeta_cleanup(void)
uhash_close(gCanonicalIDCache);
gCanonicalIDCache = NULL;
}
gCanonicalIDCacheInitialized = FALSE;
gCanonicalIDCacheInitOnce.reset();
if (gOlsonToMeta != NULL) {
uhash_close(gOlsonToMeta);
gOlsonToMeta = NULL;
}
gOlsonToMetaInitialized = FALSE;
gOlsonToMetaInitOnce.reset();
if (gMetaZoneIDTable != NULL) {
uhash_close(gMetaZoneIDTable);
gMetaZoneIDTable = NULL;
}
// delete after closing gMetaZoneIDTable, because it holds
// value objects held by the hashtable
delete gMetaZoneIDs;
gMetaZoneIDsInitialized = FALSE;
gMetaZoneIDs = NULL;
gMetaZoneIDsInitOnce.reset();
delete gSingleZoneCountries;
gSingleZoneCountries = NULL;
delete gMultiZonesCountries;
gCountryInfoVectorsInitialized = FALSE;
gMultiZonesCountries = NULL;
gCountryInfoVectorsInitOnce.reset();
return TRUE;
}
@ -212,6 +216,19 @@ parseDate (const UChar *text, UErrorCode &status) {
return 0;
}
static void U_CALLCONV initCanonicalIDCache(UErrorCode &status) {
gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
if (gCanonicalIDCache == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(status)) {
gCanonicalIDCache = NULL;
}
// No key/value deleters - keys/values are from a resource bundle
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
}
const UChar* U_EXPORT2
ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) {
if (U_FAILURE(status)) {
@ -225,27 +242,9 @@ ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) {
}
// Checking the cached results
UBool initialized;
UMTX_CHECK(&gZoneMetaLock, gCanonicalIDCacheInitialized, initialized);
if (!initialized) {
// Create empty hashtable
umtx_lock(&gZoneMetaLock);
{
if (!gCanonicalIDCacheInitialized) {
gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
if (gCanonicalIDCache == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(status)) {
gCanonicalIDCache = NULL;
return NULL;
}
// No key/value deleters - keys/values are from a resource bundle
gCanonicalIDCacheInitialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
}
}
umtx_unlock(&gZoneMetaLock);
umtx_initOnce(gCanonicalIDCacheInitOnce, &initCanonicalIDCache, status);
if (U_FAILURE(status)) {
return NULL;
}
const UChar *canonicalID = NULL;
@ -393,6 +392,28 @@ ZoneMeta::getCanonicalCLDRID(const TimeZone& tz) {
return getCanonicalCLDRID(tz.getID(tzID), status);
}
static void U_CALLCONV countryInfoVectorsInit(UErrorCode &status) {
// Create empty vectors
// No deleters for these UVectors, it's a reference to a resource bundle string.
gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status);
if (gSingleZoneCountries == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status);
if (gMultiZonesCountries == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(status)) {
delete gSingleZoneCountries;
delete gMultiZonesCountries;
gSingleZoneCountries = NULL;
gMultiZonesCountries = NULL;
}
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
}
UnicodeString& U_EXPORT2
ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, UBool *isPrimary /* = NULL */) {
if (isPrimary != NULL) {
@ -412,39 +433,9 @@ ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country,
// Checking the cached results
UErrorCode status = U_ZERO_ERROR;
UBool initialized;
UMTX_CHECK(&gZoneMetaLock, gCountryInfoVectorsInitialized, initialized);
if (!initialized) {
// Create empty vectors
umtx_lock(&gZoneMetaLock);
{
if (!gCountryInfoVectorsInitialized) {
// No deleters for these UVectors, it's a reference to a resource bundle string.
gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status);
if (gSingleZoneCountries == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status);
if (gMultiZonesCountries == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
if (U_SUCCESS(status)) {
gCountryInfoVectorsInitialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
} else {
delete gSingleZoneCountries;
delete gMultiZonesCountries;
}
}
}
umtx_unlock(&gZoneMetaLock);
if (U_FAILURE(status)) {
return country;
}
U_ASSERT(gSingleZoneCountries != NULL);
U_ASSERT(gMultiZonesCountries != NULL);
umtx_initOnce(gCountryInfoVectorsInitOnce, &countryInfoVectorsInit, status);
if (U_FAILURE(status)) {
return country;
}
// Check if it was already cached
@ -546,6 +537,19 @@ ZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &re
return result;
}
static void U_CALLCONV olsonToMetaInit(UErrorCode &status) {
U_ASSERT(gOlsonToMeta == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
gOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
if (U_FAILURE(status)) {
gOlsonToMeta = NULL;
} else {
uhash_setKeyDeleter(gOlsonToMeta, deleteUCharString);
uhash_setValueDeleter(gOlsonToMeta, deleteUVector);
}
}
const UVector* U_EXPORT2
ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) {
UErrorCode status = U_ZERO_ERROR;
@ -555,31 +559,9 @@ ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) {
return NULL;
}
UBool initialized;
UMTX_CHECK(&gZoneMetaLock, gOlsonToMetaInitialized, initialized);
if (!initialized) {
UHashtable *tmpOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
if (U_FAILURE(status)) {
return NULL;
}
uhash_setKeyDeleter(tmpOlsonToMeta, deleteUCharString);
uhash_setValueDeleter(tmpOlsonToMeta, deleteUVector);
umtx_lock(&gZoneMetaLock);
{
if (!gOlsonToMetaInitialized) {
gOlsonToMeta = tmpOlsonToMeta;
tmpOlsonToMeta = NULL;
gOlsonToMetaInitialized = TRUE;
}
}
umtx_unlock(&gZoneMetaLock);
// OK to call the following multiple times with the same function
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
if (tmpOlsonToMeta != NULL) {
uhash_close(tmpOlsonToMeta);
}
umtx_initOnce(gOlsonToMetaInitOnce, &olsonToMetaInit, status);
if (U_FAILURE(status)) {
return NULL;
}
// get the mapping from cache
@ -773,86 +755,79 @@ ZoneMeta::getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString &re
return result;
}
void
ZoneMeta::initAvailableMetaZoneIDs () {
UBool initialized;
UMTX_CHECK(&gZoneMetaLock, gMetaZoneIDsInitialized, initialized);
if (!initialized) {
umtx_lock(&gZoneMetaLock);
{
if (!gMetaZoneIDsInitialized) {
UErrorCode status = U_ZERO_ERROR;
UHashtable *metaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status);
uhash_setKeyDeleter(metaZoneIDTable, uprv_deleteUObject);
// No valueDeleter, because the vector maintain the value objects
UVector *metaZoneIDs = NULL;
if (U_SUCCESS(status)) {
metaZoneIDs = new UVector(NULL, uhash_compareUChars, status);
if (metaZoneIDs == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
} else {
uhash_close(metaZoneIDTable);
}
if (U_SUCCESS(status)) {
U_ASSERT(metaZoneIDs != NULL);
metaZoneIDs->setDeleter(uprv_free);
static void U_CALLCONV initAvailableMetaZoneIDs () {
U_ASSERT(gMetaZoneIDs == NULL);
U_ASSERT(gMetaZoneIDTable == NULL);
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status);
UResourceBundle res;
ures_initStackObject(&res);
while (U_SUCCESS(status) && ures_hasNext(bundle)) {
ures_getNextResource(bundle, &res, &status);
if (U_FAILURE(status)) {
break;
}
const char *mzID = ures_getKey(&res);
int32_t len = uprv_strlen(mzID);
UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1));
if (uMzID == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
break;
}
u_charsToUChars(mzID, uMzID, len);
uMzID[len] = 0;
UnicodeString *usMzID = new UnicodeString(uMzID);
if (uhash_get(metaZoneIDTable, usMzID) == NULL) {
metaZoneIDs->addElement((void *)uMzID, status);
uhash_put(metaZoneIDTable, (void *)usMzID, (void *)uMzID, &status);
} else {
uprv_free(uMzID);
delete usMzID;
}
}
if (U_SUCCESS(status)) {
gMetaZoneIDs = metaZoneIDs;
gMetaZoneIDTable = metaZoneIDTable;
gMetaZoneIDsInitialized = TRUE;
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
} else {
uhash_close(metaZoneIDTable);
delete metaZoneIDs;
}
ures_close(&res);
ures_close(bundle);
ures_close(rb);
}
}
UErrorCode status = U_ZERO_ERROR;
gMetaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status);
if (U_FAILURE(status) || gMetaZoneIDTable == NULL) {
gMetaZoneIDTable = NULL;
return;
}
uhash_setKeyDeleter(gMetaZoneIDTable, uprv_deleteUObject);
// No valueDeleter, because the vector maintain the value objects
gMetaZoneIDs = new UVector(NULL, uhash_compareUChars, status);
if (U_FAILURE(status) || gMetaZoneIDs == NULL) {
gMetaZoneIDs = NULL;
uhash_close(gMetaZoneIDTable);
gMetaZoneIDTable = NULL;
return;
}
gMetaZoneIDs->setDeleter(uprv_free);
UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status);
UResourceBundle res;
ures_initStackObject(&res);
while (U_SUCCESS(status) && ures_hasNext(bundle)) {
ures_getNextResource(bundle, &res, &status);
if (U_FAILURE(status)) {
break;
}
umtx_unlock(&gZoneMetaLock);
const char *mzID = ures_getKey(&res);
int32_t len = uprv_strlen(mzID);
UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1));
if (uMzID == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
break;
}
u_charsToUChars(mzID, uMzID, len);
uMzID[len] = 0;
UnicodeString *usMzID = new UnicodeString(uMzID);
if (uhash_get(gMetaZoneIDTable, usMzID) == NULL) {
gMetaZoneIDs->addElement((void *)uMzID, status);
uhash_put(gMetaZoneIDTable, (void *)usMzID, (void *)uMzID, &status);
} else {
uprv_free(uMzID);
delete usMzID;
}
}
ures_close(&res);
ures_close(bundle);
ures_close(rb);
if (U_FAILURE(status)) {
uhash_close(gMetaZoneIDTable);
delete gMetaZoneIDs;
gMetaZoneIDTable = NULL;
gMetaZoneIDs = NULL;
}
}
const UVector*
ZoneMeta::getAvailableMetazoneIDs() {
initAvailableMetaZoneIDs();
umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs);
return gMetaZoneIDs;
}
const UChar*
ZoneMeta::findMetaZoneID(const UnicodeString& mzid) {
initAvailableMetaZoneIDs();
umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs);
if (gMetaZoneIDTable == NULL) {
return NULL;
}
return (const UChar*)uhash_get(gMetaZoneIDTable, &mzid);
}

View file

@ -109,7 +109,6 @@ public:
private:
ZoneMeta(); // Prevent construction.
static UVector* createMetazoneMappings(const UnicodeString &tzid);
static void initAvailableMetaZoneIDs();
static UnicodeString& formatCustomID(uint8_t hour, uint8_t min, uint8_t sec, UBool negative, UnicodeString& id);
static const UChar* getShortIDFromCanonical(const UChar* canonicalID);
};