[glib/wip/mount-watcher: 11/15] GContextSpecificGroup: support for complex signals
- From: Ryan Lortie <desrt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/mount-watcher: 11/15] GContextSpecificGroup: support for complex signals
- Date: Wed, 14 Jan 2015 21:54:25 +0000 (UTC)
commit aad331059be7745535e28e35bc895a588ce9ccbf
Author: Ryan Lortie <desrt desrt ca>
Date: Thu Jan 8 21:49:34 2015 -0500
GContextSpecificGroup: support for complex signals
Add support for non-VOID__VOID signals to GContextSpecificGroup.
We keep the VOID__VOID case as a special optimised case by usual the
usual bit-stealing tricks.
gio/gappinfo.c | 2 +-
gio/gcontextspecificgroup.c | 122 +++++++++++++++++++++++++++++++++++++++----
gio/gcontextspecificgroup.h | 4 +-
gio/gunixmounts.c | 8 ++--
4 files changed, 120 insertions(+), 16 deletions(-)
---
diff --git a/gio/gappinfo.c b/gio/gappinfo.c
index fe2fa3d..4d97243 100644
--- a/gio/gappinfo.c
+++ b/gio/gappinfo.c
@@ -1131,5 +1131,5 @@ g_app_info_monitor_get (void)
void
g_app_info_monitor_fire (void)
{
- g_context_specific_group_emit (&g_app_info_monitor_group, g_app_info_monitor_changed_signal);
+ g_context_specific_group_emit (&g_app_info_monitor_group, g_app_info_monitor_changed_signal, 0);
}
diff --git a/gio/gcontextspecificgroup.c b/gio/gcontextspecificgroup.c
index ff44578..a96d049 100644
--- a/gio/gcontextspecificgroup.c
+++ b/gio/gcontextspecificgroup.c
@@ -22,8 +22,97 @@
#include "gcontextspecificgroup.h"
#include <glib-object.h>
+#include <gobject/gvaluecollector.h>
#include "glib-private.h"
+#include <string.h>
+
+typedef struct
+{
+ gint ref_count;
+ guint signal_id;
+ GQuark detail;
+ guint n_params;
+ GValue params[1];
+} GContextSpecificEmission;
+
+static GContextSpecificEmission *
+g_context_specific_emission_newv (guint signal_id,
+ GQuark detail,
+ va_list ap)
+{
+ GContextSpecificEmission *emission;
+ GSignalQuery query;
+ guint i;
+
+ g_signal_query (signal_id, &query);
+
+ if (query.n_params == 0 && detail == 0)
+ return GUINT_TO_POINTER (signal_id * 2 + 1);
+
+ emission = g_malloc (G_STRUCT_OFFSET (GContextSpecificEmission, params[query.n_params]));
+ emission->ref_count = 1;
+ emission->signal_id = signal_id;
+ emission->detail = detail;
+ emission->n_params = query.n_params;
+
+ for (i = 0; i < query.n_params; i++)
+ {
+ gchar *error;
+
+ G_VALUE_COLLECT_INIT (&emission->params[i], query.param_types[i], ap, 0, &error);
+ if (error)
+ g_error ("g_contect_specific_emission_newv: %s", error);
+ }
+
+ return emission;
+}
+
+static GContextSpecificEmission *
+g_context_specific_emission_ref (GContextSpecificEmission *emission)
+{
+ if (~GPOINTER_TO_UINT (emission) & 1)
+ g_atomic_int_inc (&emission->ref_count);
+
+ return emission;
+}
+
+static void
+g_context_specific_emission_unref (GContextSpecificEmission *emission)
+{
+ if (~GPOINTER_TO_UINT (emission) & 1)
+ {
+ if (g_atomic_int_dec_and_test (&emission->ref_count))
+ {
+ guint i;
+
+ for (i = 0; i < emission->n_params; i++)
+ g_value_reset (&emission->params[i]);
+
+ g_free (emission);
+ }
+ }
+}
+
+static void
+g_context_specific_emission_emit_on_instance (GContextSpecificEmission *emission,
+ gpointer instance)
+{
+ if (~GPOINTER_TO_UINT (emission) & 1)
+ {
+ GValue *instance_and_params;
+
+ instance_and_params = g_newa (GValue, 1 + emission->n_params);
+ instance_and_params[0].g_type = G_TYPE_FROM_INSTANCE (instance);
+ instance_and_params[0].data[0].v_pointer = instance;
+ memcpy (instance_and_params + 1, emission->params, sizeof (GValue) * emission->n_params);
+
+ g_signal_emitv (instance_and_params, emission->signal_id, emission->detail, NULL);
+ }
+ else
+ g_signal_emit (instance, GPOINTER_TO_UINT (emission) / 2, 0);
+}
+
typedef struct
{
GSource source;
@@ -39,19 +128,20 @@ g_context_specific_source_dispatch (GSource *source,
gpointer user_data)
{
GContextSpecificSource *css = (GContextSpecificSource *) source;
- guint signal_id;
+ GContextSpecificEmission *emission;
g_mutex_lock (&css->lock);
g_assert (!g_queue_is_empty (&css->pending));
- signal_id = GPOINTER_TO_UINT (g_queue_pop_head (&css->pending));
+ emission = g_queue_pop_head (&css->pending);
if (g_queue_is_empty (&css->pending))
g_source_set_ready_time (source, -1);
g_mutex_unlock (&css->lock);
- g_signal_emit (css->instance, signal_id, 0);
+ g_context_specific_emission_emit_on_instance (emission, css->instance);
+ g_context_specific_emission_unref (emission);
return TRUE;
}
@@ -61,8 +151,11 @@ g_context_specific_source_finalize (GSource *source)
{
GContextSpecificSource *css = (GContextSpecificSource *) source;
- g_mutex_clear (&css->lock);
+ while (!g_queue_is_empty (&css->pending))
+ g_context_specific_emission_unref (g_queue_pop_head (&css->pending));
+
g_queue_clear (&css->pending);
+ g_mutex_clear (&css->lock);
}
static GContextSpecificSource *
@@ -182,17 +275,23 @@ g_context_specific_group_remove (GContextSpecificGroup *group,
void
g_context_specific_group_emit (GContextSpecificGroup *group,
- guint signal_id)
+ guint signal_id,
+ GQuark detail,
+ ...)
{
+ GContextSpecificEmission *emission;
+ va_list ap;
+
+ va_start (ap, detail);
+ emission = g_context_specific_emission_newv (signal_id, detail, ap);
+ va_end (ap);
+
g_mutex_lock (&group->lock);
if (group->table)
{
GHashTableIter iter;
gpointer value;
- gpointer ptr;
-
- ptr = GUINT_TO_POINTER (signal_id);
g_hash_table_iter_init (&iter, group->table);
while (g_hash_table_iter_next (&iter, NULL, &value))
@@ -201,8 +300,9 @@ g_context_specific_group_emit (GContextSpecificGroup *group,
g_mutex_lock (&css->lock);
- g_queue_remove (&css->pending, ptr);
- g_queue_push_tail (&css->pending, ptr);
+ /* this will find repeat instances of void handlers */
+ if (!g_queue_find (&css->pending, emission))
+ g_queue_push_tail (&css->pending, g_context_specific_emission_ref (emission));
g_source_set_ready_time ((GSource *) css, 0);
@@ -211,4 +311,6 @@ g_context_specific_group_emit (GContextSpecificGroup *group,
}
g_mutex_unlock (&group->lock);
+
+ g_context_specific_emission_unref (emission);
}
diff --git a/gio/gcontextspecificgroup.h b/gio/gcontextspecificgroup.h
index bd2ea5d..5f538d4 100644
--- a/gio/gcontextspecificgroup.h
+++ b/gio/gcontextspecificgroup.h
@@ -42,6 +42,8 @@ g_context_specific_group_remove (GContextSpecificGroup *group,
void
g_context_specific_group_emit (GContextSpecificGroup *group,
- guint signal_id);
+ guint signal_id,
+ GQuark detail,
+ ...);
#endif /* __G_CONTEXT_SPECIFIC_GROUP_H__ */
diff --git a/gio/gunixmounts.c b/gio/gunixmounts.c
index 518bc44..bef3f50 100644
--- a/gio/gunixmounts.c
+++ b/gio/gunixmounts.c
@@ -1303,7 +1303,7 @@ fstab_file_changed (GFileMonitor *monitor,
event_type != G_FILE_MONITOR_EVENT_DELETED)
return;
- g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTPOINTS_CHANGED]);
+ g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTPOINTS_CHANGED], 0);
}
static void
@@ -1318,7 +1318,7 @@ mtab_file_changed (GFileMonitor *monitor,
event_type != G_FILE_MONITOR_EVENT_DELETED)
return;
- g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]);
+ g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED], 0);
}
static gboolean
@@ -1327,7 +1327,7 @@ proc_mounts_changed (GIOChannel *channel,
gpointer user_data)
{
if (cond & G_IO_ERR)
- g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED]);
+ g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTS_CHANGED], 0);
return TRUE;
}
@@ -1360,7 +1360,7 @@ mount_change_poller (gpointer user_data)
if (has_changed)
{
mount_poller_time = (guint64) g_get_monotonic_time ();
- g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTPOINTS_CHANGED]);
+ g_context_specific_group_emit (&mount_monitor_group, signals[MOUNTPOINTS_CHANGED], 0);
}
return TRUE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]