mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-09-27 17:52:58 +02:00
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.
This commit is contained in:
@@ -1131,5 +1131,5 @@ g_app_info_monitor_get (void)
|
|||||||
void
|
void
|
||||||
g_app_info_monitor_fire (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);
|
||||||
}
|
}
|
||||||
|
@@ -22,8 +22,97 @@
|
|||||||
#include "gcontextspecificgroup.h"
|
#include "gcontextspecificgroup.h"
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <gobject/gvaluecollector.h>
|
||||||
#include "glib-private.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
|
typedef struct
|
||||||
{
|
{
|
||||||
GSource source;
|
GSource source;
|
||||||
@@ -39,19 +128,20 @@ g_context_specific_source_dispatch (GSource *source,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GContextSpecificSource *css = (GContextSpecificSource *) source;
|
GContextSpecificSource *css = (GContextSpecificSource *) source;
|
||||||
guint signal_id;
|
GContextSpecificEmission *emission;
|
||||||
|
|
||||||
g_mutex_lock (&css->lock);
|
g_mutex_lock (&css->lock);
|
||||||
|
|
||||||
g_assert (!g_queue_is_empty (&css->pending));
|
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))
|
if (g_queue_is_empty (&css->pending))
|
||||||
g_source_set_ready_time (source, -1);
|
g_source_set_ready_time (source, -1);
|
||||||
|
|
||||||
g_mutex_unlock (&css->lock);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -61,8 +151,11 @@ g_context_specific_source_finalize (GSource *source)
|
|||||||
{
|
{
|
||||||
GContextSpecificSource *css = (GContextSpecificSource *) 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_queue_clear (&css->pending);
|
||||||
|
g_mutex_clear (&css->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GContextSpecificSource *
|
static GContextSpecificSource *
|
||||||
@@ -182,17 +275,23 @@ g_context_specific_group_remove (GContextSpecificGroup *group,
|
|||||||
|
|
||||||
void
|
void
|
||||||
g_context_specific_group_emit (GContextSpecificGroup *group,
|
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);
|
g_mutex_lock (&group->lock);
|
||||||
|
|
||||||
if (group->table)
|
if (group->table)
|
||||||
{
|
{
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer value;
|
gpointer value;
|
||||||
gpointer ptr;
|
|
||||||
|
|
||||||
ptr = GUINT_TO_POINTER (signal_id);
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, group->table);
|
g_hash_table_iter_init (&iter, group->table);
|
||||||
while (g_hash_table_iter_next (&iter, NULL, &value))
|
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_mutex_lock (&css->lock);
|
||||||
|
|
||||||
g_queue_remove (&css->pending, ptr);
|
/* this will find repeat instances of void handlers */
|
||||||
g_queue_push_tail (&css->pending, ptr);
|
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);
|
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_mutex_unlock (&group->lock);
|
||||||
|
|
||||||
|
g_context_specific_emission_unref (emission);
|
||||||
}
|
}
|
||||||
|
@@ -42,6 +42,8 @@ g_context_specific_group_remove (GContextSpecificGroup *group,
|
|||||||
|
|
||||||
void
|
void
|
||||||
g_context_specific_group_emit (GContextSpecificGroup *group,
|
g_context_specific_group_emit (GContextSpecificGroup *group,
|
||||||
guint signal_id);
|
guint signal_id,
|
||||||
|
GQuark detail,
|
||||||
|
...);
|
||||||
|
|
||||||
#endif /* __G_CONTEXT_SPECIFIC_GROUP_H__ */
|
#endif /* __G_CONTEXT_SPECIFIC_GROUP_H__ */
|
||||||
|
@@ -1303,7 +1303,7 @@ fstab_file_changed (GFileMonitor *monitor,
|
|||||||
event_type != G_FILE_MONITOR_EVENT_DELETED)
|
event_type != G_FILE_MONITOR_EVENT_DELETED)
|
||||||
return;
|
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
|
static void
|
||||||
@@ -1318,7 +1318,7 @@ mtab_file_changed (GFileMonitor *monitor,
|
|||||||
event_type != G_FILE_MONITOR_EVENT_DELETED)
|
event_type != G_FILE_MONITOR_EVENT_DELETED)
|
||||||
return;
|
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
|
static gboolean
|
||||||
@@ -1327,7 +1327,7 @@ proc_mounts_changed (GIOChannel *channel,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
if (cond & G_IO_ERR)
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -1360,7 +1360,7 @@ mount_change_poller (gpointer user_data)
|
|||||||
if (has_changed)
|
if (has_changed)
|
||||||
{
|
{
|
||||||
mount_poller_time = (guint64) g_get_monotonic_time ();
|
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;
|
return TRUE;
|
||||||
|
Reference in New Issue
Block a user