diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index ab599f297..cb03759fb 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -172,6 +172,10 @@
+
+ Periodic Timer
+
+
Extending GIO
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index aac6be493..24f5ca1d0 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -2911,3 +2911,29 @@ G_TYPE_PROXY
g_proxy_get_type
+
+
+gperiodic
+GPeriodic
+GPeriodic
+
+g_periodic_new
+g_periodic_get_hz
+g_periodic_get_priority
+
+GPeriodicTickFunc
+g_periodic_add
+g_periodic_remove
+
+g_periodic_block
+g_periodic_unblock
+
+GPeriodicRepairFunc
+g_periodic_damaged
+
+G_TYPE_PERIODIC
+G_PERIODIC
+G_IS_PERIODIC
+
+g_periodic_get_type
+
diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types
index c623c5a9d..ec01b40c9 100644
--- a/docs/reference/gio/gio.types
+++ b/docs/reference/gio/gio.types
@@ -74,6 +74,7 @@ g_network_service_get_type
g_output_stream_get_type
g_output_stream_splice_flags_get_type
g_password_save_get_type
+g_periodic_get_type
g_permission_get_type
g_proxy_address_enumerator_get_type
g_proxy_address_get_type
diff --git a/gio/Makefile.am b/gio/Makefile.am
index b92856b21..2aedfc102 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -347,6 +347,7 @@ libgio_2_0_la_SOURCES = \
gnetworkingprivate.h \
gnetworkservice.c \
goutputstream.c \
+ gperiodic.c \
gpermission.c \
gpollfilemonitor.c \
gpollfilemonitor.h \
@@ -502,6 +503,7 @@ gio_headers = \
gnetworkaddress.h \
gnetworkservice.h \
goutputstream.h \
+ gperiodic.h \
gpermission.h \
gproxyaddress.h \
gproxy.h \
diff --git a/gio/gio-marshal.list b/gio/gio-marshal.list
index c6c3caef4..8f859995c 100644
--- a/gio/gio-marshal.list
+++ b/gio/gio-marshal.list
@@ -24,3 +24,4 @@ VOID:STRING,BOOLEAN
VOID:POINTER,INT,STRING
BOOLEAN:OBJECT
INT:OBJECT
+VOID:UINT64
diff --git a/gio/gio.h b/gio/gio.h
index 456e909e1..c18384ff0 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -93,6 +93,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/gio/gio.symbols b/gio/gio.symbols
index af837f873..eb8a92785 100644
--- a/gio/gio.symbols
+++ b/gio/gio.symbols
@@ -1948,3 +1948,17 @@ g_simple_action_new_stateful
g_simple_action_set_enabled
#endif
#endif
+
+#if IN_HEADER(__G_PERIODIC_H__)
+#if IN_FILE(__G_PERIODIC_C__)
+g_periodic_block
+g_periodic_damaged
+g_periodic_get_hz
+g_periodic_get_priority
+g_periodic_get_type
+g_periodic_new
+g_periodic_add
+g_periodic_remove
+g_periodic_unblock
+#endif
+#endif
diff --git a/gio/gperiodic.c b/gio/gperiodic.c
new file mode 100644
index 000000000..190877646
--- /dev/null
+++ b/gio/gperiodic.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library 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.
+ *
+ * Author: Ryan Lortie
+ */
+
+#include "config.h"
+
+#include "gperiodic.h"
+
+#include "gio-marshal.h"
+
+/**
+ * SECTION:gperiodic
+ * @title: GPeriodic
+ * @short_description: a periodic event clock
+ *
+ * #GPeriodic is a periodic event clock that fires a configurable number
+ * of times per second and is capable of being put into synch with an
+ * external time source.
+ *
+ * A number of #GPeriodicTickFuncs are registered with
+ * g_periodic_add() and are called each time the clock "ticks".
+ *
+ * The tick functions can report "damage" (ie: updates that need to be
+ * performed) that are handled in a "repair" phase that follows all the
+ * tick functions having been run. It is also possible to report damage
+ * while the clock is not running, in which case the rate of repairs
+ * will be rate limited as if the clock were running.
+ *
+ * #GPeriodic is intended to be used as a paint clock for managing
+ * geometry updates and painting of windows.
+ *
+ * Since: 2.28
+ **/
+
+/**
+ * GPeriodic:
+ *
+ * #GPeriodic is an opaque structure type.
+ *
+ * Since: 2.28
+ **/
+
+typedef GObjectClass GPeriodicClass;
+
+typedef struct
+{
+ GPeriodicTickFunc callback;
+ gpointer user_data;
+ GDestroyNotify notify;
+ guint id;
+} GPeriodicTick;
+
+typedef struct
+{
+ GPeriodicRepairFunc callback;
+ gpointer user_data;
+ GDestroyNotify notify;
+} GPeriodicRepair;
+
+typedef struct
+{
+ GSource source;
+ GPeriodic *periodic;
+} GPeriodicSource;
+
+struct _GPeriodic
+{
+ GObject parent_instance;
+ GSource *source; /* GPeriodicSource */
+ guint64 last_run;
+ guint blocked;
+ guint hz;
+
+ GSList *ticks; /* List */
+ GSList *repairs; /* List */
+
+ /* debug */
+ guint in_tick : 1;
+ guint in_repair : 1;
+};
+
+G_DEFINE_TYPE (GPeriodic, g_periodic, G_TYPE_OBJECT)
+
+#define PERIODIC_FROM_SOURCE(src) (((GPeriodicSource *) (src))->periodic)
+
+enum
+{
+ PROP_NONE,
+ PROP_HZ,
+ PROP_PRIORITY
+};
+
+static guint g_periodic_tick;
+static guint g_periodic_repair;
+
+static guint64
+g_periodic_get_milliticks (GPeriodic *periodic)
+{
+ guint64 microticks;
+ GTimeVal timeval;
+
+ g_source_get_current_time (periodic->source, &timeval);
+
+ microticks = timeval.tv_sec;
+ microticks *= 1000000;
+ microticks += timeval.tv_usec;
+ microticks *= periodic->hz;
+
+ return microticks / 1000;
+}
+
+static void
+g_periodic_run (GPeriodic *periodic)
+{
+ g_assert (periodic->blocked == 0);
+
+ if (periodic->ticks)
+ {
+ GSList *iter;
+
+ periodic->in_tick = TRUE;
+ for (iter = periodic->ticks; iter; iter = iter->next)
+ {
+ GPeriodicTick *tick = iter->data;
+
+ tick->callback (periodic, periodic->last_run, tick->user_data);
+ }
+ g_signal_emit (periodic, g_periodic_tick, 0, periodic->last_run);
+ periodic->in_tick = FALSE;
+ }
+
+ g_assert (periodic->blocked == 0);
+
+ if (periodic->repairs)
+ {
+ periodic->in_repair = TRUE;
+ while (periodic->repairs)
+ {
+ GPeriodicRepair *repair = periodic->repairs->data;
+
+ repair->callback (periodic, repair->user_data);
+
+ periodic->repairs = g_slist_remove (periodic->repairs, repair);
+
+ if (repair->notify)
+ repair->notify (repair->user_data);
+
+ g_slice_free (GPeriodicRepair, repair);
+ }
+ g_signal_emit (periodic, g_periodic_repair, 0);
+ periodic->in_repair = FALSE;
+ }
+}
+
+static gboolean
+g_periodic_prepare (GSource *source,
+ gint *timeout)
+{
+ GPeriodic *periodic = PERIODIC_FROM_SOURCE (source);
+
+ if ((periodic->ticks || periodic->repairs) && !periodic->blocked)
+ /* We need to run. */
+ {
+ gint64 remaining;
+
+ remaining = periodic->last_run + 1000 -
+ g_periodic_get_milliticks (periodic);
+
+ if (remaining > 0)
+ /* It's too soon. Wait some more before running. */
+ {
+ /* Round-up the timeout.
+ *
+ * If we round down, then we will quite often wake to discover
+ * that not enough time has passed and want to sleep again, so
+ * save ourselves the future bother.
+ */
+ *timeout = (remaining + periodic->hz - 1) / periodic->hz;
+
+ return FALSE;
+ }
+
+ else
+ /* Enough time has passed. Run now. */
+ {
+ *timeout = 0;
+ return TRUE;
+ }
+ }
+ else
+ /* We shouldn't be running now at all. */
+ {
+ *timeout = -1;
+ return FALSE;
+ }
+}
+
+static gboolean
+g_periodic_check (GSource *source)
+{
+ GPeriodic *periodic = PERIODIC_FROM_SOURCE (source);
+
+ if ((periodic->ticks || periodic->repairs) && !periodic->blocked)
+ /* We need to run. */
+ {
+ guint64 now = g_periodic_get_milliticks (periodic);
+
+ /* Run if it's not too soon. */
+ return !(now < periodic->last_run + 1000);
+ }
+
+ else
+ /* We shouldn't be running now at all. */
+ return FALSE;
+}
+
+static gboolean
+g_periodic_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ GPeriodic *periodic = PERIODIC_FROM_SOURCE (source);
+ guint64 elapsed_ticks;
+ guint64 now;
+
+ g_assert (periodic->blocked == 0);
+
+ /* Update the last_run.
+ *
+ * In the normal case we want to add exactly 1 tick to it. This
+ * ensures that the clock runs at the proper rate in the normal case
+ * (ie: the dispatch overhead time is not lost).
+ *
+ * If more than one tick has elapsed, we set it equal to the current
+ * time. This has two purposes:
+ *
+ * - sets last_run to something reasonable if the clock is running
+ * for the first time or after a long period of inactivity
+ *
+ * - resets our stride if we missed a frame
+ */
+ now = g_periodic_get_milliticks (periodic);
+ elapsed_ticks = (now - periodic->last_run) / 1000;
+ g_assert (elapsed_ticks > 0);
+
+ if G_LIKELY (elapsed_ticks == 1)
+ periodic->last_run += 1000;
+ else
+ periodic->last_run = now;
+
+ g_periodic_run (periodic);
+
+ return TRUE;
+}
+
+static void
+g_periodic_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ GPeriodic *periodic = G_PERIODIC (object);
+
+ switch (prop_id)
+ {
+ case PROP_PRIORITY:
+ g_value_set_int (value, g_source_get_priority (periodic->source));
+ break;
+
+ case PROP_HZ:
+ g_value_set_uint (value, periodic->hz);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+g_periodic_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ GPeriodic *periodic = G_PERIODIC (object);
+
+ switch (prop_id)
+ {
+ case PROP_PRIORITY:
+ g_source_set_priority (periodic->source, g_value_get_int (value));
+ break;
+
+ case PROP_HZ:
+ periodic->hz = g_value_get_uint (value);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+static void
+g_periodic_finalize (GObject *object)
+{
+ GPeriodic *periodic = G_PERIODIC (object);
+
+ g_source_destroy (periodic->source);
+ g_source_unref (periodic->source);
+
+ G_OBJECT_CLASS (g_periodic_parent_class)
+ ->finalize (object);
+}
+
+static void
+g_periodic_init (GPeriodic *periodic)
+{
+ static GSourceFuncs source_funcs = {
+ g_periodic_prepare, g_periodic_check, g_periodic_dispatch
+ };
+
+ periodic->source = g_source_new (&source_funcs, sizeof (GPeriodicSource));
+ ((GPeriodicSource *) periodic->source)->periodic = periodic;
+ g_source_attach (periodic->source, g_main_context_get_thread_default ());
+}
+
+static void
+g_periodic_class_init (GObjectClass *class)
+{
+ class->get_property = g_periodic_get_property;
+ class->set_property = g_periodic_set_property;
+ class->finalize = g_periodic_finalize;
+
+ g_periodic_tick = g_signal_new ("tick", G_TYPE_PERIODIC,
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ _gio_marshal_VOID__UINT64,
+ G_TYPE_NONE, 1, G_TYPE_UINT64);
+ g_periodic_repair = g_signal_new ("repair", G_TYPE_PERIODIC,
+ G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property (class, PROP_HZ,
+ g_param_spec_uint ("hz", "ticks per second",
+ "rate (in Hz) at which the 'tick' signal is emitted",
+ 1, 120, 1, G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (class, PROP_PRIORITY,
+ g_param_spec_int ("priority", "priority level",
+ "the GSource priority level to run at",
+ G_MININT, G_MAXINT, 0, G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+}
+
+/**
+ * g_periodic_block:
+ * @periodic: a #GPeriodic clock
+ *
+ * Temporarily blocks @periodic from running in order to bring it in
+ * synch with an external time source.
+ *
+ * This function must be called from a handler of the "repair" signal.
+ *
+ * If this function is called, emission of the tick signal will be
+ * suspended until g_periodic_unblock() is called an equal number of
+ * times. Once that happens, the "tick" signal will run immediately and
+ * future "tick" signals will be emitted relative to the time at which
+ * the last call to g_periodic_unblock() occured.
+ *
+ * Since: 2.28
+ **/
+void
+g_periodic_block (GPeriodic *periodic)
+{
+ g_return_if_fail (G_IS_PERIODIC (periodic));
+ g_return_if_fail (periodic->in_repair);
+
+ periodic->blocked++;
+}
+
+/**
+ * g_periodic_unblock:
+ * @periodic: a #GPeriodic clock
+ *
+ * Reverses the effect of a previous call to g_periodic_block().
+ *
+ * If this call removes the last block, the tick signal is immediately
+ * run. The repair signal may also be run if the clock is marked as
+ * damaged.
+ *
+ * This function may not be called from handlers of any signal emitted
+ * by @periodic.
+ *
+ * Since: 2.28
+ **/
+void
+g_periodic_unblock (GPeriodic *periodic)
+{
+ g_return_if_fail (G_IS_PERIODIC (periodic));
+ g_return_if_fail (!periodic->in_repair);
+ g_return_if_fail (!periodic->in_tick);
+ g_return_if_fail (periodic->blocked);
+
+ if (--periodic->blocked)
+ {
+ periodic->last_run = g_periodic_get_milliticks (periodic);
+ g_periodic_run (periodic);
+ }
+}
+
+/**
+ * g_periodic_add:
+ * @periodic: a #GPeriodic clock
+ * @callback: a #GPeriodicTickFunc function
+ * @user_data: data for @callback
+ * @notify: for freeing @user_data when it is no longer needed
+ *
+ * Request periodic calls to @callback to start. The periodicity of the
+ * calls is determined by the 'hz' property.
+ *
+ * This function may not be called from a handler of the repair signal,
+ * but it is perfectly reasonable to call it from a handler of the tick
+ * signal.
+ *
+ * The callback may be cancelled later by using g_periodic_remove() on
+ * the return value of this function.
+ *
+ * Returns: a non-zero tag identifying this callback
+ *
+ * Since: 2.28
+ **/
+/**
+ * GPeriodicTickFunc:
+ * @periodic: the #GPeriodic clock that is ticking
+ * @timestamp: the timestamp at the time of the tick
+ * @user_data: the user data given to g_periodic_add()
+ *
+ * The signature of the callback function that is called when the
+ * #GPeriodic clock ticks.
+ *
+ * The @timestamp parameter is equal for all callbacks called during a
+ * particular tick on a given clock.
+ *
+ * Since: 2.28
+ **/
+guint
+g_periodic_add (GPeriodic *periodic,
+ GPeriodicTickFunc callback,
+ gpointer user_data,
+ GDestroyNotify notify)
+{
+ GPeriodicTick *tick;
+ static guint id;
+
+ g_return_val_if_fail (G_IS_PERIODIC (periodic), 0);
+ g_return_val_if_fail (!periodic->in_repair, 0);
+
+ tick = g_slice_new (GPeriodicTick);
+ tick->callback = callback;
+ tick->user_data = user_data;
+ tick->notify = notify;
+ tick->id = ++id;
+
+ periodic->ticks = g_slist_prepend (periodic->ticks, tick);
+
+ return tick->id;
+}
+
+/**
+ * g_periodic_remove:
+ * @periodic: a #GPeriodic clock
+ * @tag: the ID of the callback to remove
+ *
+ * Reverse the effect of a previous call to g_periodic_start().
+ *
+ * @tag is the ID returned by that function.
+ *
+ * This function may not be called from a handler of the repair signal,
+ * but it is perfectly reasonable to call it from a handler of the tick
+ * signal.
+ *
+ * Since: 2.28
+ **/
+void
+g_periodic_remove (GPeriodic *periodic,
+ guint tag)
+{
+ GSList **iter;
+
+ g_return_if_fail (G_IS_PERIODIC (periodic));
+ g_return_if_fail (!periodic->in_repair);
+
+ for (iter = &periodic->ticks; *iter; iter = &(*iter)->next)
+ {
+ GPeriodicTick *tick = (*iter)->data;
+
+ if (tick->id == tag)
+ {
+ /* do this first incase the destroy notify re-enters */
+ *iter = g_slist_remove (*iter, tick);
+
+ if (tick->notify)
+ tick->notify (tick->user_data);
+
+ g_slice_free (GPeriodicTick, tick);
+ return;
+ }
+ }
+
+ g_critical ("GPeriodic: tag %u not registered", tag);
+}
+
+/**
+ * g_periodic_damaged:
+ * @periodic: a #GPeriodic clock
+ * @callback: a #GPeriodicRepairFunc
+ * @user_data: data for @callback
+ * @notify: for freeing @user_data when it is no longer needed
+ *
+ * Report damage and schedule @callback to be called during the next
+ * repair phase. Multiple registrations result in multiple invocations,
+ * so you should track for yourself if you are already registered.
+ *
+ * You may not call this function during the repair phase.
+ *
+ * Since: 2.28
+ **/
+/**
+ * GPeriodicRepairFunc:
+ * @periodic: the #GPeriodic clock that the damage was reported to
+ * @user_data: the user data given to g_periodic_damaged()
+ *
+ * The signature of the callback function that is called during the
+ * repair phase when damaged was reported using g_periodic_damaged().
+ *
+ * Since: 2.28
+ **/
+void
+g_periodic_damaged (GPeriodic *periodic,
+ GPeriodicRepairFunc callback,
+ gpointer user_data,
+ GDestroyNotify notify)
+{
+ GPeriodicRepair *repair;
+
+ g_return_if_fail (G_IS_PERIODIC (periodic));
+ g_return_if_fail (!periodic->in_repair);
+
+ repair = g_slice_new (GPeriodicRepair);
+ repair->callback = callback;
+ repair->user_data = user_data;
+ repair->notify = notify;
+
+ periodic->repairs = g_slist_prepend (periodic->repairs, repair);
+}
+
+/**
+ * g_periodic_get_hz:
+ * @periodic: a #GPeriodic clock
+ *
+ * Gets the frequency of the clock.
+ *
+ * Returns: the frquency of the clock, in Hz
+ *
+ * Since: 2.28
+ **/
+guint
+g_periodic_get_hz (GPeriodic *periodic)
+{
+ return periodic->hz;
+}
+
+/**
+ * g_periodic_get_priority:
+ * @periodic: a #GPeriodic clock
+ *
+ * Gets the #GSource priority of the clock.
+ *
+ * Returns: the priority level
+ *
+ * Since: 2.28
+ **/
+gint
+g_periodic_get_priority (GPeriodic *periodic)
+{
+ return g_source_get_priority (periodic->source);
+}
+
+/**
+ * g_periodic_new:
+ * @hz: the frequency of the new clock in Hz (between 1 and 120)
+ * @priority: the #GSource priority to run at
+ *
+ * Creates a new #GPeriodic clock.
+ *
+ * The created clock is attached to the thread-default main context in
+ * effect at the time of the call to this function. See
+ * g_main_context_push_thread_default() for more information.
+ *
+ * Due to the fact that #GMainContext is only accurate to the nearest
+ * millisecond, the frequency can not meaningfully get too close to
+ * 1000. For this reason, it is arbitrarily bounded at 120.
+ *
+ * Returns: a new #GPeriodic
+ *
+ * Since: 2.28
+ **/
+GPeriodic *
+g_periodic_new (guint hz,
+ gint priority)
+{
+ g_return_val_if_fail (1 <= hz && hz <= 120, NULL);
+
+ return g_object_new (G_TYPE_PERIODIC,
+ "hz", hz,
+ "priority", priority,
+ NULL);
+}
diff --git a/gio/gperiodic.h b/gio/gperiodic.h
new file mode 100644
index 000000000..dd3fec271
--- /dev/null
+++ b/gio/gperiodic.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright © 2010 Codethink Limited
+ *
+ * This library 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.
+ *
+ * Author: Ryan Lortie
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only can be included directly."
+#endif
+
+#ifndef __G_PERIODIC_H__
+#define __G_PERIODIC_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define G_TYPE_PERIODIC (g_periodic_get_type ())
+#define G_PERIODIC(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \
+ G_TYPE_PERIODIC, GPeriodic))
+#define G_IS_PERIODIC(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_PERIODIC))
+
+typedef struct _GPeriodic GPeriodic;
+
+typedef void (* GPeriodicTickFunc) (GPeriodic *periodic,
+ guint64 timestamp,
+ gpointer user_data);
+typedef void (* GPeriodicRepairFunc) (GPeriodic *periodic,
+ gpointer user_data);
+
+GType g_periodic_get_type (void);
+GPeriodic * g_periodic_new (guint hz,
+ gint priority);
+guint g_periodic_get_hz (GPeriodic *periodic);
+gint g_periodic_get_priority (GPeriodic *periodic);
+
+guint g_periodic_add (GPeriodic *periodic,
+ GPeriodicTickFunc callback,
+ gpointer user_data,
+ GDestroyNotify notify);
+void g_periodic_remove (GPeriodic *periodic,
+ guint tag);
+
+void g_periodic_block (GPeriodic *periodic);
+void g_periodic_unblock (GPeriodic *periodic);
+
+void g_periodic_damaged (GPeriodic *periodic,
+ GPeriodicRepairFunc callback,
+ gpointer user_data,
+ GDestroyNotify notify);
+
+G_END_DECLS
+
+#endif /* __G_PERIODIC_H__ */