diff options
author | rim <rozhuk.im@gmail.com> | 2019-10-25 17:27:49 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2019-10-25 17:27:49 +0000 |
commit | 551e83662de9815d161a82c760cfa77995905740 (patch) | |
tree | efdf104f6d17d0e56107f0af4fd2d6d31ab446b2 | |
parent | 5e17a98d1947b4090e661ae114f37653d9126dc3 (diff) | |
download | glib-551e83662de9815d161a82c760cfa77995905740.tar.gz |
gtimezone: Cache UTC and local TZ indefinitely
Previously, these GTimeZone objects were being cached in the `time_zones` cache, but dropped from it when their final ref was dropped (which was frequently). That meant additional reads of `/etc/localtime` next time they were created, which was noticeable on profiles. Keep a permanent ref to the UTC and local timezones.
-rw-r--r-- | glib/gtimezone.c | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/glib/gtimezone.c b/glib/gtimezone.c index 3933621e2..5d2efcbf3 100644 --- a/glib/gtimezone.c +++ b/glib/gtimezone.c @@ -37,6 +37,7 @@ #include "gslice.h" #include "gdatetime.h" #include "gdate.h" +#include "genviron.h" #ifdef G_OS_WIN32 @@ -196,6 +197,8 @@ struct _GTimeZone G_LOCK_DEFINE_STATIC (time_zones); static GHashTable/*<string?, GTimeZone>*/ *time_zones; +G_LOCK_DEFINE_STATIC (tz_local); +static GTimeZone *tz_local = NULL; #define MIN_TZYEAR 1916 /* Daylight Savings started in WWI */ #define MAX_TZYEAR 2999 /* And it's not likely ever to go away, but @@ -1657,10 +1660,20 @@ g_time_zone_new (const gchar *identifier) * * Since: 2.26 **/ +static gpointer +g_time_zone_utc_init (gpointer data) +{ + return g_time_zone_new ("UTC"); +} + GTimeZone * g_time_zone_new_utc (void) { - return g_time_zone_new ("UTC"); + static GOnce utc_once = G_ONCE_INIT; + + g_once (&utc_once, g_time_zone_utc_init, NULL); + + return g_time_zone_ref ((GTimeZone *)utc_once.retval); } /** @@ -1683,7 +1696,23 @@ g_time_zone_new_utc (void) GTimeZone * g_time_zone_new_local (void) { - return g_time_zone_new (getenv ("TZ")); + const gchar *tzenv = g_getenv ("TZ"); + GTimeZone *tz; + + G_LOCK (tz_local); + + /* Is time zone changed and must be flushed? */ + 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); + + tz = g_time_zone_ref (tz_local); + + G_UNLOCK (tz_local); + + return tz; } /** |