[glib] GPeriodic: a periodic event clock



commit 5400b0b38c513c829a4f0b0fc59188f820435d79
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Oct 20 03:20:34 2010 +0200

    GPeriodic: a periodic event clock
    
    Add a new class, GPeriodic.
    
    We hope to use this as a paint clock that can be shared by GTK and
    Clutter.  Many changes are still expected to the API.

 docs/reference/gio/gio-docs.xml     |    4 +
 docs/reference/gio/gio-sections.txt |   26 ++
 docs/reference/gio/gio.types        |    1 +
 gio/Makefile.am                     |    2 +
 gio/gio-marshal.list                |    1 +
 gio/gio.h                           |    1 +
 gio/gio.symbols                     |   14 +
 gio/gperiodic.c                     |  631 +++++++++++++++++++++++++++++++++++
 gio/gperiodic.h                     |   69 ++++
 9 files changed, 749 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gio/gio-docs.xml b/docs/reference/gio/gio-docs.xml
index ab599f2..cb03759 100644
--- a/docs/reference/gio/gio-docs.xml
+++ b/docs/reference/gio/gio-docs.xml
@@ -172,6 +172,10 @@
         <xi:include href="xml/gapplication.xml"/>
         <xi:include href="xml/gapplicationcommandline.xml"/>
     </chapter>
+    <chapter id="periodic">
+        <title>Periodic Timer</title>
+        <xi:include href="xml/gperiodic.xml"/>
+    </chapter>
     <chapter id="extending">
         <title>Extending GIO</title>
         <xi:include href="xml/gvfs.xml"/>
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index aac6be4..24f5ca1 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -2911,3 +2911,29 @@ G_TYPE_PROXY
 <SUBSECTION Private>
 g_proxy_get_type
 </SECTION>
+
+<SECTION>
+<FILE>gperiodic</FILE>
+<TITLE>GPeriodic</TITLE>
+GPeriodic
+<SUBSECTION>
+g_periodic_new
+g_periodic_get_hz
+g_periodic_get_priority
+<SUBSECTION>
+GPeriodicTickFunc
+g_periodic_add
+g_periodic_remove
+<SUBSECTION>
+g_periodic_block
+g_periodic_unblock
+<SUBSECTION>
+GPeriodicRepairFunc
+g_periodic_damaged
+<SUBSECTION Standard>
+G_TYPE_PERIODIC
+G_PERIODIC
+G_IS_PERIODIC
+<SUBSECTION Private>
+g_periodic_get_type
+</SECTION>
diff --git a/docs/reference/gio/gio.types b/docs/reference/gio/gio.types
index c623c5a..ec01b40 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 b92856b..2aedfc1 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 c6c3cae..8f85999 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 456e909..c18384f 100644
--- a/gio/gio.h
+++ b/gio/gio.h
@@ -93,6 +93,7 @@
 #include <gio/gnetworkaddress.h>
 #include <gio/gnetworkservice.h>
 #include <gio/goutputstream.h>
+#include <gio/gperiodic.h>
 #include <gio/gpermission.h>
 #include <gio/gproxy.h>
 #include <gio/gproxyaddress.h>
diff --git a/gio/gio.symbols b/gio/gio.symbols
index af837f8..eb8a927 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 0000000..1908776
--- /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 <desrt desrt ca>
+ */
+
+#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 #GPeriodicTickFunc<!-- -->s 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<GPeriodicTick> */
+  GSList  *repairs;           /* List<GPeriodicRepair> */
+
+  /* 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 0000000..dd3fec2
--- /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 <desrt desrt ca>
+ */
+
+#if !defined (__GIO_GIO_H_INSIDE__) && !defined (GIO_COMPILATION)
+#error "Only <gio/gio.h> can be included directly."
+#endif
+
+#ifndef __G_PERIODIC_H__
+#define __G_PERIODIC_H__
+
+#include <glib-object.h>
+
+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__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]