GTimeZoneMonitor: Revert addition of this class

The main rationale for adding it was to avoid having gnome-shell
mmap'ing /etc/localtime once a second.  However, we can just as easily
run inotify there, and given no one else was clamoring for a way to
detect when the time zone changes, I don't see a need for public API
here - at least not yet.

In the bigger picture, I just don't believe that the vast majority of
applications are going to go out of their way to instantiate and keep
around a random GTimeZoneMonitor class.  And if they do, it's has the
side effect that for other bits of code in the process, local GDateTime
instances may start varying again!

So, if code can't rely on local GDateTime instances being in a
consistent state anyways, let's just do that always.  The
documentation now says that this is the case.  Applications have
always been able to work in a consistent local time zone by
instantiating a zone and then using it for GDateTime constructors.

We fix the "gnome-shell stats /etc/localtime once a second" issue by
using timerfd (in glib) and inotify (in gnome-shell).

https://bugzilla.gnome.org/show_bug.cgi?id=655129
This commit is contained in:
Colin Walters 2011-08-19 03:27:16 -04:00
parent 5fbf3c93b2
commit 5b68b49b20
12 changed files with 5 additions and 305 deletions

View File

@ -3252,19 +3252,6 @@ G_TLS_CONSOLE_INTERACTION_GET_CLASS
g_tls_console_interaction_get_type
</SECTION>
<SECTION>
<FILE>gtimezonemonitor</FILE>
<TITLE>GTimeZoneMonitor</TITLE>
GTimeZoneMonitor
g_time_zone_monitor_get
<SUBSECTION Standard>
G_IS_TIME_ZONE_MONITOR
G_TIME_ZONE_MONITOR
G_TYPE_TIME_ZONE_MONITOR
<SUBSECTION Private>
g_time_zone_monitor_get_type
</SECTION>
<SECTION>
<FILE>gdbusinterface</FILE>
<TITLE>GDBusInterface</TITLE>

View File

@ -138,7 +138,6 @@ g_dbus_server_get_type
g_dbus_auth_observer_get_type
g_credentials_get_type
g_unix_credentials_message_get_type
g_time_zone_monitor_get_type
g_dbus_interface_get_type
g_dbus_interface_skeleton_get_type
g_dbus_object_get_type

View File

@ -1448,8 +1448,6 @@ g_time_zone_new
g_time_zone_new_local
g_time_zone_new_utc
<SUBSECTION>
g_time_zone_refresh_local
<SUBSECTION>
GTimeType
g_time_zone_find_interval
g_time_zone_adjust_time

View File

@ -377,7 +377,6 @@ libgio_2_0_la_SOURCES = \
gthemedicon.c \
gthreadedresolver.c \
gthreadedresolver.h \
gtimezonemonitor.c \
gtlsbackend.c \
gtlscertificate.c \
gtlsclientconnection.c \
@ -534,7 +533,6 @@ gio_headers = \
gtcpwrapperconnection.h \
gthreadedsocketservice.h\
gthemedicon.h \
gtimezonemonitor.h \
gtlsbackend.h \
gtlscertificate.h \
gtlsclientconnection.h \

View File

@ -119,7 +119,6 @@
#include <gio/gtcpwrapperconnection.h>
#include <gio/gthemedicon.h>
#include <gio/gthreadedsocketservice.h>
#include <gio/gtimezonemonitor.h>
#include <gio/gtlsbackend.h>
#include <gio/gtlscertificate.h>
#include <gio/gtlsclientconnection.h>

View File

@ -1493,8 +1493,6 @@ g_tls_password_set_value_full
g_tls_password_set_warning
g_tls_password_get_flags
g_tls_password_get_description
g_time_zone_monitor_get_type
g_time_zone_monitor_get
g_dbus_interface_get_info
g_dbus_interface_get_object
g_dbus_interface_get_type

View File

@ -1,156 +0,0 @@
/*
* Copyright © 2011 Codethink Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the licence or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
#include "gtimezonemonitor.h"
#include "gfile.h"
/**
* SECTION:gtimezonemonitor
* @title: GTimeZoneMonitor
* @short_description: Monitor the local timezone
*
* #GTimeZoneMonitor is a utility class to monitor the local timezone for
* changes (ie: in response to the user manually changing the timezone
* to that of a different locale).
*
* You must use this class in order for your program to notice changes
* to the local timezone. It works by monitoring the /etc/localtime
* file. When the timezone is found to have changed,
* g_time_zone_refresh_local() is called and the "changed" signal is
* emitted on the #GTimeZoneMonitor (in that order).
*
* Windows support is not presently working.
**/
/**
* GTimeZoneMonitor:
*
* This is an opaque structure type.
**/
typedef GObjectClass GTimeZoneMonitorClass;
struct _GTimeZoneMonitor
{
GObject parent_instance;
GFileMonitor *monitor;
};
G_DEFINE_TYPE (GTimeZoneMonitor, g_time_zone_monitor, G_TYPE_OBJECT)
static guint g_time_zone_monitor_changed_signal;
static void
etc_localtime_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
GTimeZoneMonitor *tzm = user_data;
if (event_type != G_FILE_MONITOR_EVENT_CREATED)
return;
g_time_zone_refresh_local ();
g_signal_emit (tzm, g_time_zone_monitor_changed_signal, 0);
}
static void
g_time_zone_monitor_finalize (GObject *object)
{
g_assert_not_reached ();
}
static void
g_time_zone_monitor_init (GTimeZoneMonitor *tzm)
{
GFile *etc_localtime;
etc_localtime = g_file_new_for_path ("/etc/localtime");
tzm->monitor = g_file_monitor_file (etc_localtime, 0, NULL, NULL);
g_object_unref (etc_localtime);
g_signal_connect (tzm->monitor, "changed",
G_CALLBACK (etc_localtime_changed), tzm);
}
static void
g_time_zone_monitor_class_init (GTimeZoneMonitorClass *class)
{
class->finalize = g_time_zone_monitor_finalize;
/**
* GTimeZoneMonitor::changed
* @monitor: the #GTimeZoneMonitor
*
* Indicates that the local timezone has changed.
*
* The g_time_zone_refresh_local() function is called just before this
* signal is emitted, so any new #GTimeZone or #GDateTime instances
* created from signal handlers will be as per the new timezone.
*
* Note that this signal is not emitted in response to entering or
* exiting daylight savings time within a given timezone. It's only
* for when the user has changed the timezone to that of a different
* location.
**/
g_time_zone_monitor_changed_signal =
g_signal_new ("changed", G_TYPE_TIME_ZONE_MONITOR,
G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
/**
* g_time_zone_monitor_get:
*
* Gets the singleton instance of the #GTimeZoneMonitor class, creating
* it if required.
*
* You should call g_object_unref() on the result when you no longer
* need it. Be aware, though, that this will not destroy the instance,
* so if you connected to the changed signal, you are required to
* disconnect from it for yourself.
*
* There is only one instance of #GTimeZoneMonitor and it dispatches its
* signals via the default #GMainContext. There is no way to create an
* instance that will dispatch signals using a different context.
*
* Returns: (transfer full): a reference to the #GTimeZoneMonitor.
**/
GTimeZoneMonitor *
g_time_zone_monitor_get (void)
{
static gsize instance;
if (g_once_init_enter (&instance))
{
GTimeZoneMonitor *monitor;
monitor = g_object_new (G_TYPE_TIME_ZONE_MONITOR, NULL);
g_once_init_leave (&instance, (gsize) monitor);
}
return g_object_ref ((void *) instance);
}

View File

@ -1,47 +0,0 @@
/*
* Copyright © 2011 Codethink Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2 of the licence or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Authors: Ryan Lortie <desrt@desrt.ca>
*/
#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
#error "Only <gio/gio.h> can be included directly."
#endif
#ifndef __G_TIME_ZONE_MONITOR_H__
#define __G_TIME_ZONE_MONITOR_H__
#include "gactiongroup.h"
G_BEGIN_DECLS
#define G_TYPE_TIME_ZONE_MONITOR (g_time_zone_monitor_get_type ())
#define G_TIME_ZONE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
G_TYPE_TIME_ZONE_MONITOR, GTimeZoneMonitor))
#define G_IS_TIME_ZONE_MONITOR(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \
G_TYPE_TIME_ZONE_MONITOR))
typedef struct _GTimeZoneMonitor GTimeZoneMonitor;
GType g_time_zone_monitor_get_type (void) G_GNUC_CONST;
GTimeZoneMonitor * g_time_zone_monitor_get (void);
G_END_DECLS
#endif /* __G_TIME_ZONE_MONITOR_H__ */

View File

@ -300,7 +300,6 @@ g_date_time_to_unix
g_date_time_to_utc
g_date_time_unref
g_time_zone_new
g_time_zone_refresh_local
g_time_zone_new_local
g_time_zone_new_utc
g_time_zone_ref

View File

@ -129,9 +129,6 @@ struct _GTimeZone
gint ref_count;
};
G_LOCK_DEFINE_STATIC (local_timezone);
static GTimeZone *local_timezone;
G_LOCK_DEFINE_STATIC (time_zones);
static GHashTable/*<string?, GTimeZone>*/ *time_zones;
@ -155,21 +152,6 @@ again:
if (ref_count == 1)
{
if G_UNLIKELY (tz == local_timezone)
{
g_critical ("The last reference on the local timezone was just "
"dropped, but GTimeZone itself still owns one. This "
"means that g_time_zone_unref() was called too many "
"times. Returning without lowering the refcount.");
/* We don't want to just inc this back again since if there
* are refcounting bugs in the code then maybe we are already
* at -1 and inc will just take us back to 0. Set to 1 to be
* sure.
*/
return;
}
if (tz->name != NULL)
{
G_LOCK(time_zones);
@ -468,12 +450,13 @@ g_time_zone_new_utc (void)
/**
* g_time_zone_new_local:
*
* Creates a #GTimeZone corresponding to local time.
* Creates a #GTimeZone corresponding to local time. The local time
* zone may change between invocations to this function; for example,
* if the system administrator changes it.
*
* This is equivalent to calling g_time_zone_new() with the value of the
* <varname>TZ</varname> environment variable (including the possibility
* of %NULL). Changes made to <varname>TZ</varname> after the first
* call to this function may or may not be noticed by future calls.
* of %NULL).
*
* You should release the return value by calling g_time_zone_unref()
* when you are done with it.
@ -485,46 +468,7 @@ g_time_zone_new_utc (void)
GTimeZone *
g_time_zone_new_local (void)
{
GTimeZone *result;
G_LOCK (local_timezone);
if (local_timezone == NULL)
local_timezone = g_time_zone_new (getenv ("TZ"));
result = g_time_zone_ref (local_timezone);
G_UNLOCK (local_timezone);
return result;
}
/**
* g_time_zone_refresh_local:
*
* Notifies #GTimeZone that the local timezone may have changed.
*
* In response, #GTimeZone will drop its cache of the local time zone.
* No existing #GTimeZone will be modified and no #GDateTime will change
* its timezone but future calls to g_time_zone_new_local() will start
* returning the new timezone.
*
* #GTimeZone does no monitoring of the local timezone on its own, which
* is why you have to call this function to notify it of the change.
*
* If you use #GTimeZoneMonitor to watch for changes then this function
* will automatically be called for you.
**/
void
g_time_zone_refresh_local (void)
{
GTimeZone *drop_this_ref = NULL;
G_LOCK (local_timezone);
drop_this_ref = local_timezone;
local_timezone = NULL;
G_UNLOCK (local_timezone);
if (drop_this_ref)
g_time_zone_unref (drop_this_ref);
return g_time_zone_new (getenv ("TZ"));
}
/* Internal helpers {{{1 */

View File

@ -54,8 +54,6 @@ typedef enum
G_TIME_TYPE_UNIVERSAL
} GTimeType;
void g_time_zone_refresh_local (void);
GTimeZone * g_time_zone_new (const gchar *identifier);
GTimeZone * g_time_zone_new_utc (void);
GTimeZone * g_time_zone_new_local (void);

View File

@ -1108,22 +1108,6 @@ test_z (void)
g_free (p);
}
static void
test_refresh (void)
{
GTimeZone *zone;
zone = g_time_zone_new (NULL);
g_assert (zone != NULL);
g_time_zone_unref (zone);
g_time_zone_refresh_local ();
zone = g_time_zone_new (NULL);
g_assert (zone != NULL);
g_time_zone_unref (zone);
}
gint
main (gint argc,
gchar *argv[])
@ -1170,7 +1154,6 @@ main (gint argc,
g_test_add_func ("/GDateTime/dst", test_GDateTime_dst);
g_test_add_func ("/GDateTime/test_z", test_z);
g_test_add_func ("/GDateTime/test-all-dates", test_all_dates);
g_test_add_func ("/GDateTime/refresh", test_refresh);
return g_test_run ();
}