/*
*******************************************************************************
- * Copyright (C) 1997-2011, International Business Machines Corporation and
+ * Copyright (C) 1997-2013, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*
********************************************************************************
*/
-#include <typeinfo> // for 'typeid' to work
+#include "utypeinfo.h" // for 'typeid' to work
#include "unicode/utypes.h"
#include "unicode/smpdtfmt.h"
#include "gregoimp.h"
+#include "umutex.h"
U_NAMESPACE_BEGIN
void
SimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
- int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) /*const*/ {
+ int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
}
UBool
-SimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ {
+SimpleTimeZone::getNextTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
if (!useDaylight) {
return FALSE;
}
UErrorCode status = U_ZERO_ERROR;
- initTransitionRules(status);
+ checkTransitionRules(status);
if (U_FAILURE(status)) {
return FALSE;
}
}
UBool
-SimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) /*const*/ {
+SimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTransition& result) const {
if (!useDaylight) {
return FALSE;
}
UErrorCode status = U_ZERO_ERROR;
- initTransitionRules(status);
+ checkTransitionRules(status);
if (U_FAILURE(status)) {
return FALSE;
}
clearTransitionRules();
}
+/*
+ * 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;
+
+void
+SimpleTimeZone::checkTransitionRules(UErrorCode& status) const {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ umtx_lock(&gLock);
+ if (!transitionRulesInitialized) {
+ SimpleTimeZone *ncThis = const_cast<SimpleTimeZone*>(this);
+ ncThis->initTransitionRules(status);
+ }
+ umtx_unlock(&gLock);
+}
+
void
SimpleTimeZone::initTransitionRules(UErrorCode& status) {
if (U_FAILURE(status)) {
}
// Check for Null pointer
if (dtRule == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
}
// For now, use ID + "(DST)" as the name
dstRule = new AnnualTimeZoneRule(tzid+UnicodeString(DST_STR), getRawOffset(), getDSTSavings(),
// Check for Null pointer
if (dstRule == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- deleteTransitionRules();
- return;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ deleteTransitionRules();
+ return;
}
// Calculate the first DST start time
// Check for Null pointer
if (dtRule == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- deleteTransitionRules();
- return;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ deleteTransitionRules();
+ return;
}
// For now, use ID + "(STD)" as the name
stdRule = new AnnualTimeZoneRule(tzid+UnicodeString(STD_STR), getRawOffset(), 0,
//Check for Null pointer
if (stdRule == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- deleteTransitionRules();
- return;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ deleteTransitionRules();
+ return;
}
// Calculate the first STD start time
}
// Check for null pointers.
if (initialRule == NULL || firstTransition == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- deleteTransitionRules();
- return;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ deleteTransitionRules();
+ return;
}
} else {
initialRule = new InitialTimeZoneRule(tzid, getRawOffset(), 0);
// Check for null pointer.
if (initialRule == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- deleteTransitionRules();
- return;
+ status = U_MEMORY_ALLOCATION_ERROR;
+ deleteTransitionRules();
+ return;
}
}
- transitionRulesInitialized = true;
+ transitionRulesInitialized = TRUE;
}
int32_t
-SimpleTimeZone::countTransitionRules(UErrorCode& /*status*/) /*const*/ {
+SimpleTimeZone::countTransitionRules(UErrorCode& /*status*/) const {
return (useDaylight) ? 2 : 0;
}
SimpleTimeZone::getTimeZoneRules(const InitialTimeZoneRule*& initial,
const TimeZoneRule* trsrules[],
int32_t& trscount,
- UErrorCode& status) /*const*/ {
+ UErrorCode& status) const {
if (U_FAILURE(status)) {
return;
}
- initTransitionRules(status);
+ checkTransitionRules(status);
if (U_FAILURE(status)) {
return;
}