DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (b6d82b1a6b02)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
# Adds threadsafe recreateDefault() method to ICU::Timezone.

diff --git a/intl/icu/source/i18n/timezone.cpp b/intl/icu/source/i18n/timezone.cpp
--- a/intl/icu/source/i18n/timezone.cpp
+++ b/intl/icu/source/i18n/timezone.cpp
@@ -110,16 +110,22 @@ static const UChar         WORLD[] = {0x30, 0x30, 0x31, 0x00}; /* "001" */
 static const UChar         GMT_ID[] = {0x47, 0x4D, 0x54, 0x00}; /* "GMT" */
 static const UChar         UNKNOWN_ZONE_ID[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00}; /* "Etc/Unknown" */
 static const int32_t       GMT_ID_LENGTH = 3;
 static const int32_t       UNKNOWN_ZONE_ID_LENGTH = 11;
 
 static icu::TimeZone* DEFAULT_ZONE = NULL;
 static icu::UInitOnce gDefaultZoneInitOnce = U_INITONCE_INITIALIZER;
 
+// Prevents DEFAULT_ZONE from being deleted while another thread is cloning it.
+static icu::UMutex* defaultZoneMutex() {
+    static icu::UMutex gDefaultZoneMutex = U_MUTEX_INITIALIZER;
+    return &gDefaultZoneMutex;
+}
+
 alignas(icu::SimpleTimeZone)
 static char gRawGMT[sizeof(icu::SimpleTimeZone)];
 
 alignas(icu::SimpleTimeZone)
 static char gRawUNKNOWN[sizeof(icu::SimpleTimeZone)];
 
 static icu::UInitOnce gStaticZonesInitOnce = U_INITONCE_INITIALIZER;
 static UBool gStaticZonesInitialized = FALSE; // Whether the static zones are initialized and ready to use.
@@ -566,26 +572,36 @@ static void U_CALLCONV initDefault()
 }
 
 // -------------------------------------
 
 TimeZone* U_EXPORT2
 TimeZone::createDefault()
 {
     umtx_initOnce(gDefaultZoneInitOnce, initDefault);
+
+    icu::Mutex mutex_lock(defaultZoneMutex());
     return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
 }
 
+void
+TimeZone::recreateDefault()
+{
+    TimeZone *default_zone = TimeZone::detectHostTimeZone();
+    adoptDefault(default_zone);
+}
+
 // -------------------------------------
 
 void U_EXPORT2
 TimeZone::adoptDefault(TimeZone* zone)
 {
     if (zone != NULL)
     {
+        icu::Mutex mutex_lock(defaultZoneMutex());
         TimeZone *old = DEFAULT_ZONE;
         DEFAULT_ZONE = zone;
         delete old;
         ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
     }
 }
 // -------------------------------------
 
diff --git a/intl/icu/source/i18n/unicode/timezone.h b/intl/icu/source/i18n/unicode/timezone.h
--- a/intl/icu/source/i18n/unicode/timezone.h
+++ b/intl/icu/source/i18n/unicode/timezone.h
@@ -310,16 +310,19 @@ class U_I18N_API TimeZone : public UObject {
      *
      * @return   A default TimeZone. Clients are responsible for deleting the time zone
      *           object returned.
      * @see getUnknown
      * @stable ICU 2.0
      */
     static TimeZone* U_EXPORT2 createDefault(void);
 
+#define ICU_TZ_HAS_RECREATE_DEFAULT
+    static void U_EXPORT2 recreateDefault();
+
     /**
      * 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 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