600 lines
20 KiB
Diff
600 lines
20 KiB
Diff
|
From b4138bd4acc04ad572dfa042a384aaaa6e4621ad Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= <antoniof@gnome.org>
|
||
|
Date: Wed, 23 Sep 2020 18:13:47 +0100
|
||
|
Subject: [PATCH 1/4] gtimezone: Split out fallback timezone identification for
|
||
|
unix
|
||
|
|
||
|
When the TZ environment variable is not set, we get the local timezone
|
||
|
identifier by reading specific files.
|
||
|
|
||
|
We are going to need these identifiers earlier, so split this logic into
|
||
|
its own function, in preparation for the next commit.
|
||
|
|
||
|
Based on idea proposed by Sebastian Keller <skeller@gnome.org>.
|
||
|
---
|
||
|
glib/gtimezone.c | 127 +++++++++++++++++++++++++++--------------------
|
||
|
1 file changed, 73 insertions(+), 54 deletions(-)
|
||
|
|
||
|
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
|
||
|
index ef67ec50b..d90a9bb73 100644
|
||
|
--- a/glib/gtimezone.c
|
||
|
+++ b/glib/gtimezone.c
|
||
|
@@ -438,11 +438,80 @@ zone_for_constant_offset (GTimeZone *gtz, const gchar *name)
|
||
|
}
|
||
|
|
||
|
#ifdef G_OS_UNIX
|
||
|
+static gchar *
|
||
|
+zone_identifier_unix (void)
|
||
|
+{
|
||
|
+ gchar *resolved_identifier = NULL;
|
||
|
+ gsize prefix_len = 0;
|
||
|
+ gchar *canonical_path = NULL;
|
||
|
+ GError *read_link_err = NULL;
|
||
|
+ const gchar *tzdir;
|
||
|
+
|
||
|
+ /* Resolve the actual timezone pointed to by /etc/localtime. */
|
||
|
+ resolved_identifier = g_file_read_link ("/etc/localtime", &read_link_err);
|
||
|
+ if (resolved_identifier == NULL)
|
||
|
+ {
|
||
|
+ gboolean not_a_symlink = g_error_matches (read_link_err,
|
||
|
+ G_FILE_ERROR,
|
||
|
+ G_FILE_ERROR_INVAL);
|
||
|
+ g_clear_error (&read_link_err);
|
||
|
+
|
||
|
+ /* Fallback to the content of /var/db/zoneinfo or /etc/timezone
|
||
|
+ * if /etc/localtime is not a symlink. /var/db/zoneinfo is
|
||
|
+ * where 'tzsetup' program on FreeBSD and DragonflyBSD stores
|
||
|
+ * the timezone chosen by the user. /etc/timezone is where user
|
||
|
+ * choice is expressed on Gentoo OpenRC and others. */
|
||
|
+ if (not_a_symlink && (g_file_get_contents ("/var/db/zoneinfo",
|
||
|
+ &resolved_identifier,
|
||
|
+ NULL, NULL) ||
|
||
|
+ g_file_get_contents ("/etc/timezone",
|
||
|
+ &resolved_identifier,
|
||
|
+ NULL, NULL)))
|
||
|
+ g_strchomp (resolved_identifier);
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Error */
|
||
|
+ g_assert (resolved_identifier == NULL);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Resolve relative path */
|
||
|
+ canonical_path = g_canonicalize_filename (resolved_identifier, "/etc");
|
||
|
+ g_free (resolved_identifier);
|
||
|
+ resolved_identifier = g_steal_pointer (&canonical_path);
|
||
|
+ }
|
||
|
+
|
||
|
+ tzdir = g_getenv ("TZDIR");
|
||
|
+ if (tzdir == NULL)
|
||
|
+ tzdir = "/usr/share/zoneinfo";
|
||
|
+
|
||
|
+ /* Strip the prefix and slashes if possible. */
|
||
|
+ if (g_str_has_prefix (resolved_identifier, tzdir))
|
||
|
+ {
|
||
|
+ prefix_len = strlen (tzdir);
|
||
|
+ while (*(resolved_identifier + prefix_len) == '/')
|
||
|
+ prefix_len++;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (prefix_len > 0)
|
||
|
+ memmove (resolved_identifier, resolved_identifier + prefix_len,
|
||
|
+ strlen (resolved_identifier) - prefix_len + 1 /* nul terminator */);
|
||
|
+
|
||
|
+ g_assert (resolved_identifier != NULL);
|
||
|
+
|
||
|
+out:
|
||
|
+ g_free (canonical_path);
|
||
|
+
|
||
|
+ return resolved_identifier;
|
||
|
+}
|
||
|
+
|
||
|
static GBytes*
|
||
|
zone_info_unix (const gchar *identifier,
|
||
|
gchar **out_identifier)
|
||
|
{
|
||
|
- gchar *filename;
|
||
|
+ gchar *filename = NULL;
|
||
|
GMappedFile *file = NULL;
|
||
|
GBytes *zoneinfo = NULL;
|
||
|
gchar *resolved_identifier = NULL;
|
||
|
@@ -470,61 +539,11 @@ zone_info_unix (const gchar *identifier,
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- gsize prefix_len = 0;
|
||
|
- gchar *canonical_path = NULL;
|
||
|
- GError *read_link_err = NULL;
|
||
|
-
|
||
|
- filename = g_strdup ("/etc/localtime");
|
||
|
-
|
||
|
- /* Resolve the actual timezone pointed to by /etc/localtime. */
|
||
|
- resolved_identifier = g_file_read_link (filename, &read_link_err);
|
||
|
+ resolved_identifier = zone_identifier_unix ();
|
||
|
if (resolved_identifier == NULL)
|
||
|
- {
|
||
|
- gboolean not_a_symlink = g_error_matches (read_link_err,
|
||
|
- G_FILE_ERROR,
|
||
|
- G_FILE_ERROR_INVAL);
|
||
|
- g_clear_error (&read_link_err);
|
||
|
-
|
||
|
- /* Fallback to the content of /var/db/zoneinfo or /etc/timezone
|
||
|
- * if /etc/localtime is not a symlink. /var/db/zoneinfo is
|
||
|
- * where 'tzsetup' program on FreeBSD and DragonflyBSD stores
|
||
|
- * the timezone chosen by the user. /etc/timezone is where user
|
||
|
- * choice is expressed on Gentoo OpenRC and others. */
|
||
|
- if (not_a_symlink && (g_file_get_contents ("/var/db/zoneinfo",
|
||
|
- &resolved_identifier,
|
||
|
- NULL, NULL) ||
|
||
|
- g_file_get_contents ("/etc/timezone",
|
||
|
- &resolved_identifier,
|
||
|
- NULL, NULL)))
|
||
|
- g_strchomp (resolved_identifier);
|
||
|
- else
|
||
|
- {
|
||
|
- /* Error */
|
||
|
- g_assert (resolved_identifier == NULL);
|
||
|
- goto out;
|
||
|
- }
|
||
|
- }
|
||
|
- else
|
||
|
- {
|
||
|
- /* Resolve relative path */
|
||
|
- canonical_path = g_canonicalize_filename (resolved_identifier, "/etc");
|
||
|
- g_free (resolved_identifier);
|
||
|
- resolved_identifier = g_steal_pointer (&canonical_path);
|
||
|
- }
|
||
|
+ goto out;
|
||
|
|
||
|
- /* Strip the prefix and slashes if possible. */
|
||
|
- if (g_str_has_prefix (resolved_identifier, tzdir))
|
||
|
- {
|
||
|
- prefix_len = strlen (tzdir);
|
||
|
- while (*(resolved_identifier + prefix_len) == '/')
|
||
|
- prefix_len++;
|
||
|
- }
|
||
|
-
|
||
|
- if (prefix_len > 0)
|
||
|
- memmove (resolved_identifier, resolved_identifier + prefix_len,
|
||
|
- strlen (resolved_identifier) - prefix_len + 1 /* nul terminator */);
|
||
|
-
|
||
|
- g_free (canonical_path);
|
||
|
+ filename = g_strdup ("/etc/localtime");
|
||
|
}
|
||
|
|
||
|
file = g_mapped_file_new (filename, FALSE, NULL);
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 7e59a4c0d5ab8e08fe2cf596fb9512708e183de8 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= <antoniof@gnome.org>
|
||
|
Date: Wed, 23 Sep 2020 18:28:40 +0100
|
||
|
Subject: [PATCH 2/4] gtimezone: Set resolved_identifier earlier
|
||
|
|
||
|
We have been passing a &resolved_identifier address around for multiple
|
||
|
functions to set it. Each function may either:
|
||
|
|
||
|
1. leaving it for the next function to set, if returning early;
|
||
|
2. set it to a duplicate of the passed identifier, if not NULL;
|
||
|
3. get a fallback value and set it, otherwise.
|
||
|
|
||
|
This can be simplified by setting it early to either:
|
||
|
|
||
|
1. a duplicate of the passed identifier, if not NULL;
|
||
|
2. a fallback value, otherwise.
|
||
|
|
||
|
This way we can avoid some unnecessary string duplication and freeing.
|
||
|
Also, on Windows, we avoid calling windows_default_tzname() twice.
|
||
|
|
||
|
But the main motivation for this change is enabling the performance
|
||
|
optimization in the next commit.
|
||
|
---
|
||
|
glib/gtimezone.c | 76 ++++++++++++++++--------------------------------
|
||
|
1 file changed, 25 insertions(+), 51 deletions(-)
|
||
|
|
||
|
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
|
||
|
index d90a9bb73..40064c9ab 100644
|
||
|
--- a/glib/gtimezone.c
|
||
|
+++ b/glib/gtimezone.c
|
||
|
@@ -508,13 +508,12 @@ out:
|
||
|
}
|
||
|
|
||
|
static GBytes*
|
||
|
-zone_info_unix (const gchar *identifier,
|
||
|
- gchar **out_identifier)
|
||
|
+zone_info_unix (const gchar *identifier,
|
||
|
+ const gchar *resolved_identifier)
|
||
|
{
|
||
|
gchar *filename = NULL;
|
||
|
GMappedFile *file = NULL;
|
||
|
GBytes *zoneinfo = NULL;
|
||
|
- gchar *resolved_identifier = NULL;
|
||
|
const gchar *tzdir;
|
||
|
|
||
|
tzdir = g_getenv ("TZDIR");
|
||
|
@@ -527,8 +526,6 @@ zone_info_unix (const gchar *identifier,
|
||
|
glibc allows both syntaxes, so we should too */
|
||
|
if (identifier != NULL)
|
||
|
{
|
||
|
- resolved_identifier = g_strdup (identifier);
|
||
|
-
|
||
|
if (*identifier == ':')
|
||
|
identifier ++;
|
||
|
|
||
|
@@ -539,7 +536,6 @@ zone_info_unix (const gchar *identifier,
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
- resolved_identifier = zone_identifier_unix ();
|
||
|
if (resolved_identifier == NULL)
|
||
|
goto out;
|
||
|
|
||
|
@@ -559,10 +555,6 @@ zone_info_unix (const gchar *identifier,
|
||
|
g_assert (resolved_identifier != NULL);
|
||
|
|
||
|
out:
|
||
|
- if (out_identifier != NULL)
|
||
|
- *out_identifier = g_steal_pointer (&resolved_identifier);
|
||
|
-
|
||
|
- g_free (resolved_identifier);
|
||
|
g_free (filename);
|
||
|
|
||
|
return zoneinfo;
|
||
|
@@ -834,14 +826,13 @@ register_tzi_to_tzi (RegTZI *reg, TIME_ZONE_INFORMATION *tzi)
|
||
|
|
||
|
static guint
|
||
|
rules_from_windows_time_zone (const gchar *identifier,
|
||
|
- gchar **out_identifier,
|
||
|
- TimeZoneRule **rules,
|
||
|
- gboolean copy_identifier)
|
||
|
+ const gchar *resolved_identifier,
|
||
|
+ TimeZoneRule **rules)
|
||
|
{
|
||
|
HKEY key;
|
||
|
gchar *subkey = NULL;
|
||
|
gchar *subkey_dynamic = NULL;
|
||
|
- gchar *key_name = NULL;
|
||
|
+ const gchar *key_name;
|
||
|
const gchar *reg_key =
|
||
|
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\";
|
||
|
TIME_ZONE_INFORMATION tzi;
|
||
|
@@ -856,19 +847,15 @@ rules_from_windows_time_zone (const gchar *identifier,
|
||
|
if (GetSystemDirectoryW (winsyspath, MAX_PATH) == 0)
|
||
|
return 0;
|
||
|
|
||
|
- g_assert (copy_identifier == FALSE || out_identifier != NULL);
|
||
|
g_assert (rules != NULL);
|
||
|
|
||
|
- if (copy_identifier)
|
||
|
- *out_identifier = NULL;
|
||
|
-
|
||
|
*rules = NULL;
|
||
|
key_name = NULL;
|
||
|
|
||
|
if (!identifier)
|
||
|
- key_name = windows_default_tzname ();
|
||
|
+ key_name = resolved_identifier;
|
||
|
else
|
||
|
- key_name = g_strdup (identifier);
|
||
|
+ key_name = identifier;
|
||
|
|
||
|
if (!key_name)
|
||
|
return 0;
|
||
|
@@ -1011,16 +998,9 @@ utf16_conv_failed:
|
||
|
else
|
||
|
(*rules)[rules_num - 1].start_year = (*rules)[rules_num - 2].start_year + 1;
|
||
|
|
||
|
- if (copy_identifier)
|
||
|
- *out_identifier = g_steal_pointer (&key_name);
|
||
|
- else
|
||
|
- g_free (key_name);
|
||
|
-
|
||
|
return rules_num;
|
||
|
}
|
||
|
|
||
|
- g_free (key_name);
|
||
|
-
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -1521,16 +1501,13 @@ parse_identifier_boundaries (gchar **pos, TimeZoneRule *tzr)
|
||
|
*/
|
||
|
static guint
|
||
|
rules_from_identifier (const gchar *identifier,
|
||
|
- gchar **out_identifier,
|
||
|
TimeZoneRule **rules)
|
||
|
{
|
||
|
gchar *pos;
|
||
|
TimeZoneRule tzr;
|
||
|
|
||
|
- g_assert (out_identifier != NULL);
|
||
|
g_assert (rules != NULL);
|
||
|
|
||
|
- *out_identifier = NULL;
|
||
|
*rules = NULL;
|
||
|
|
||
|
if (!identifier)
|
||
|
@@ -1545,7 +1522,6 @@ rules_from_identifier (const gchar *identifier,
|
||
|
|
||
|
if (*pos == 0)
|
||
|
{
|
||
|
- *out_identifier = g_strdup (identifier);
|
||
|
return create_ruleset_from_rule (rules, &tzr);
|
||
|
}
|
||
|
|
||
|
@@ -1566,14 +1542,8 @@ rules_from_identifier (const gchar *identifier,
|
||
|
/* Use US rules, Windows' default is Pacific Standard Time */
|
||
|
if ((rules_num = rules_from_windows_time_zone ("Pacific Standard Time",
|
||
|
NULL,
|
||
|
- rules,
|
||
|
- FALSE)))
|
||
|
+ rules)))
|
||
|
{
|
||
|
- /* We don't want to hardcode our identifier here as
|
||
|
- * "Pacific Standard Time", use what was passed in
|
||
|
- */
|
||
|
- *out_identifier = g_strdup (identifier);
|
||
|
-
|
||
|
for (i = 0; i < rules_num - 1; i++)
|
||
|
{
|
||
|
(*rules)[i].std_offset = - tzr.std_offset;
|
||
|
@@ -1594,7 +1564,6 @@ rules_from_identifier (const gchar *identifier,
|
||
|
if (!parse_identifier_boundaries (&pos, &tzr))
|
||
|
return 0;
|
||
|
|
||
|
- *out_identifier = g_strdup (identifier);
|
||
|
return create_ruleset_from_rule (rules, &tzr);
|
||
|
}
|
||
|
|
||
|
@@ -1605,17 +1574,13 @@ parse_footertz (const gchar *footer, size_t footerlen)
|
||
|
gchar *tzstring = g_strndup (footer + 1, footerlen - 2);
|
||
|
GTimeZone *footertz = NULL;
|
||
|
|
||
|
- /* FIXME: it might make sense to modify rules_from_identifier to
|
||
|
- allow NULL to be passed instead of &ident, saving the strdup/free
|
||
|
- pair. The allocation for tzstring could also be avoided by
|
||
|
+ /* FIXME: The allocation for tzstring could be avoided by
|
||
|
passing a gsize identifier_len argument to rules_from_identifier
|
||
|
and changing the code in that function to stop assuming that
|
||
|
identifier is nul-terminated. */
|
||
|
- gchar *ident;
|
||
|
TimeZoneRule *rules;
|
||
|
- guint rules_num = rules_from_identifier (tzstring, &ident, &rules);
|
||
|
+ guint rules_num = rules_from_identifier (tzstring, &rules);
|
||
|
|
||
|
- g_free (ident);
|
||
|
g_free (tzstring);
|
||
|
if (rules_num > 1)
|
||
|
{
|
||
|
@@ -1723,6 +1688,16 @@ g_time_zone_new (const gchar *identifier)
|
||
|
G_UNLOCK (time_zones);
|
||
|
return tz;
|
||
|
}
|
||
|
+ else
|
||
|
+ resolved_identifier = g_strdup (identifier);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+#ifdef G_OS_UNIX
|
||
|
+ resolved_identifier = zone_identifier_unix ();
|
||
|
+#elif defined (G_OS_WIN32)
|
||
|
+ resolved_identifier = windows_default_tzname ();
|
||
|
+#endif
|
||
|
}
|
||
|
|
||
|
tz = g_slice_new0 (GTimeZone);
|
||
|
@@ -1731,7 +1706,7 @@ g_time_zone_new (const gchar *identifier)
|
||
|
zone_for_constant_offset (tz, identifier);
|
||
|
|
||
|
if (tz->t_info == NULL &&
|
||
|
- (rules_num = rules_from_identifier (identifier, &resolved_identifier, &rules)))
|
||
|
+ (rules_num = rules_from_identifier (identifier, &rules)))
|
||
|
{
|
||
|
init_zone_from_rules (tz, rules, rules_num, g_steal_pointer (&resolved_identifier));
|
||
|
g_free (rules);
|
||
|
@@ -1740,7 +1715,7 @@ g_time_zone_new (const gchar *identifier)
|
||
|
if (tz->t_info == NULL)
|
||
|
{
|
||
|
#ifdef G_OS_UNIX
|
||
|
- GBytes *zoneinfo = zone_info_unix (identifier, &resolved_identifier);
|
||
|
+ GBytes *zoneinfo = zone_info_unix (identifier, resolved_identifier);
|
||
|
if (zoneinfo != NULL)
|
||
|
{
|
||
|
init_zone_from_iana_info (tz, zoneinfo, g_steal_pointer (&resolved_identifier));
|
||
|
@@ -1748,9 +1723,8 @@ g_time_zone_new (const gchar *identifier)
|
||
|
}
|
||
|
#elif defined (G_OS_WIN32)
|
||
|
if ((rules_num = rules_from_windows_time_zone (identifier,
|
||
|
- &resolved_identifier,
|
||
|
- &rules,
|
||
|
- TRUE)))
|
||
|
+ resolved_identifier,
|
||
|
+ &rules)))
|
||
|
{
|
||
|
init_zone_from_rules (tz, rules, rules_num, g_steal_pointer (&resolved_identifier));
|
||
|
g_free (rules);
|
||
|
@@ -1777,7 +1751,7 @@ g_time_zone_new (const gchar *identifier)
|
||
|
rules[0].start_year = MIN_TZYEAR;
|
||
|
rules[1].start_year = MAX_TZYEAR;
|
||
|
|
||
|
- init_zone_from_rules (tz, rules, 2, windows_default_tzname ());
|
||
|
+ init_zone_from_rules (tz, rules, 2, g_steal_pointer (&resolved_identifier));
|
||
|
}
|
||
|
|
||
|
g_free (rules);
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 5237b4984306847dff05db54b5c12c83662f2f1d Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= <antoniof@gnome.org>
|
||
|
Date: Thu, 1 Oct 2020 21:11:44 +0100
|
||
|
Subject: [PATCH 3/4] gtimezone: Cache default timezone indefinitely
|
||
|
|
||
|
We cache GTimeZone instances to avoid expensive construction when the
|
||
|
same id is requested again.
|
||
|
|
||
|
However, if the NULL id is passed to g_time_zone_new(), we always
|
||
|
construct a new instance for the default/fallback timezone.
|
||
|
|
||
|
With the recent introduction of some heavy calculations[1], repeated
|
||
|
instance construction in such cases has visible performance impact in
|
||
|
nautilus list view and other such GtkTreeView consumers.
|
||
|
|
||
|
To avoid this, cache reference to a constructed default timezone and
|
||
|
use it the next time g_time_zone_new() is called with NULL argument,
|
||
|
as long as the default identifier doesn't change. We already did the
|
||
|
same for the local timezone[2].
|
||
|
|
||
|
Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/2204
|
||
|
|
||
|
Based on idea proposed by Sebastian Keller <skeller@gnome.org>.
|
||
|
|
||
|
[1] 25d950b61f92f25cc9ab20d683aa4d6969f93098
|
||
|
[2] 551e83662de9815d161a82c760cfa77995905740
|
||
|
---
|
||
|
glib/gtimezone.c | 37 ++++++++++++++++++++++++++++++++-----
|
||
|
1 file changed, 32 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
|
||
|
index 40064c9ab..035da2f45 100644
|
||
|
--- a/glib/gtimezone.c
|
||
|
+++ b/glib/gtimezone.c
|
||
|
@@ -195,6 +195,8 @@ struct _GTimeZone
|
||
|
|
||
|
G_LOCK_DEFINE_STATIC (time_zones);
|
||
|
static GHashTable/*<string?, GTimeZone>*/ *time_zones;
|
||
|
+G_LOCK_DEFINE_STATIC (tz_default);
|
||
|
+static GTimeZone *tz_default = NULL;
|
||
|
G_LOCK_DEFINE_STATIC (tz_local);
|
||
|
static gchar *tzenv_cached = NULL;
|
||
|
static GTimeZone *tz_local = NULL;
|
||
|
@@ -1675,12 +1677,12 @@ g_time_zone_new (const gchar *identifier)
|
||
|
gint rules_num;
|
||
|
gchar *resolved_identifier = NULL;
|
||
|
|
||
|
- G_LOCK (time_zones);
|
||
|
- if (time_zones == NULL)
|
||
|
- time_zones = g_hash_table_new (g_str_hash, g_str_equal);
|
||
|
-
|
||
|
if (identifier)
|
||
|
{
|
||
|
+ G_LOCK (time_zones);
|
||
|
+ if (time_zones == NULL)
|
||
|
+ time_zones = g_hash_table_new (g_str_hash, g_str_equal);
|
||
|
+
|
||
|
tz = g_hash_table_lookup (time_zones, identifier);
|
||
|
if (tz)
|
||
|
{
|
||
|
@@ -1693,11 +1695,26 @@ g_time_zone_new (const gchar *identifier)
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
+ G_LOCK (tz_default);
|
||
|
#ifdef G_OS_UNIX
|
||
|
resolved_identifier = zone_identifier_unix ();
|
||
|
#elif defined (G_OS_WIN32)
|
||
|
resolved_identifier = windows_default_tzname ();
|
||
|
#endif
|
||
|
+ if (tz_default)
|
||
|
+ {
|
||
|
+ /* Flush default if changed */
|
||
|
+ if (g_strcmp0 (tz_default->name, resolved_identifier))
|
||
|
+ g_clear_pointer (&tz_default, g_time_zone_unref);
|
||
|
+ else
|
||
|
+ {
|
||
|
+ tz = g_time_zone_ref (tz_default);
|
||
|
+ G_UNLOCK (tz_default);
|
||
|
+
|
||
|
+ g_free (resolved_identifier);
|
||
|
+ return tz;
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
tz = g_slice_new0 (GTimeZone);
|
||
|
@@ -1773,9 +1790,19 @@ g_time_zone_new (const gchar *identifier)
|
||
|
{
|
||
|
if (identifier)
|
||
|
g_hash_table_insert (time_zones, tz->name, tz);
|
||
|
+ else if (tz->name)
|
||
|
+ {
|
||
|
+ /* Caching reference */
|
||
|
+ g_atomic_int_inc (&tz->ref_count);
|
||
|
+ tz_default = tz;
|
||
|
+ }
|
||
|
}
|
||
|
g_atomic_int_inc (&tz->ref_count);
|
||
|
- G_UNLOCK (time_zones);
|
||
|
+
|
||
|
+ if (identifier)
|
||
|
+ G_UNLOCK (time_zones);
|
||
|
+ else
|
||
|
+ G_UNLOCK (tz_default);
|
||
|
|
||
|
return tz;
|
||
|
}
|
||
|
--
|
||
|
GitLab
|
||
|
|
||
|
|
||
|
From 02753644b33660a175d1a9b1ea9e8717c314ef23 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Ant=C3=B3nio=20Fernandes?= <antoniof@gnome.org>
|
||
|
Date: Wed, 23 Sep 2020 19:36:49 +0100
|
||
|
Subject: [PATCH 4/4] Revert "gtimezone: Cache timezones based on the
|
||
|
identifier they were created by"
|
||
|
|
||
|
This reverts commit 851241f19a3fd9ec693b3dd8f37a84c7f970984a.
|
||
|
|
||
|
That commit avoids a performance regression but introduces a behavior regression:
|
||
|
changes to /etc/localtime have no effect for the remaining of the application's
|
||
|
runtime.
|
||
|
|
||
|
With the optimization introduced by the previous commit, we can pass NULL to
|
||
|
g_time_zone_new() repeatedly with no performance drawback, so we no longer have
|
||
|
to workaround this case.
|
||
|
---
|
||
|
glib/gtimezone.c | 13 +++----------
|
||
|
1 file changed, 3 insertions(+), 10 deletions(-)
|
||
|
|
||
|
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
|
||
|
index 035da2f45..8e38bb549 100644
|
||
|
--- a/glib/gtimezone.c
|
||
|
+++ b/glib/gtimezone.c
|
||
|
@@ -198,7 +198,6 @@ static GHashTable/*<string?, GTimeZone>*/ *time_zones;
|
||
|
G_LOCK_DEFINE_STATIC (tz_default);
|
||
|
static GTimeZone *tz_default = NULL;
|
||
|
G_LOCK_DEFINE_STATIC (tz_local);
|
||
|
-static gchar *tzenv_cached = NULL;
|
||
|
static GTimeZone *tz_local = NULL;
|
||
|
|
||
|
#define MIN_TZYEAR 1916 /* Daylight Savings started in WWI */
|
||
|
@@ -1863,17 +1862,11 @@ g_time_zone_new_local (void)
|
||
|
G_LOCK (tz_local);
|
||
|
|
||
|
/* Is time zone changed and must be flushed? */
|
||
|
- if (tz_local && g_strcmp0 (tzenv, tzenv_cached) != 0)
|
||
|
- {
|
||
|
- g_clear_pointer (&tz_local, g_time_zone_unref);
|
||
|
- g_clear_pointer (&tzenv_cached, g_free);
|
||
|
- }
|
||
|
+ if (tz_local && g_strcmp0 (g_time_zone_get_identifier (tz_local), tzenv))
|
||
|
+ g_clear_pointer (&tz_local, g_time_zone_unref);
|
||
|
|
||
|
if (tz_local == NULL)
|
||
|
- {
|
||
|
- tz_local = g_time_zone_new (tzenv);
|
||
|
- tzenv_cached = g_strdup (tzenv);
|
||
|
- }
|
||
|
+ tz_local = g_time_zone_new (tzenv);
|
||
|
|
||
|
tz = g_time_zone_ref (tz_local);
|
||
|
|
||
|
--
|
||
|
GitLab
|
||
|
|