summaryrefslogtreecommitdiff
path: root/gobject
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2012-03-05 12:29:45 +0100
committerAlexander Larsson <alexl@redhat.com>2012-03-05 12:29:45 +0100
commitf3fb42cfaf967cec4450437d81f824de266fb274 (patch)
treeb6cf954c7982fe2dbe0c2d4d487003562b46bcf8 /gobject
parente9c399a65bfa1796947a8d1d65a4a7edab610c3b (diff)
parent2d6502f67bb207c5a0d6eaba27b2398b74baa28f (diff)
downloadglib-f3fb42cfaf967cec4450437d81f824de266fb274.tar.gz
Merge branch 'signal-performance'
Diffstat (limited to 'gobject')
-rw-r--r--gobject/gclosure.c481
-rw-r--r--gobject/gclosure.h24
-rw-r--r--gobject/glib-genmarshal.c232
-rw-r--r--gobject/gmarshal.c909
-rw-r--r--gobject/gmarshal.h154
-rw-r--r--gobject/gsignal.c461
-rw-r--r--gobject/gsignal.h11
-rw-r--r--gobject/gtype-private.h27
-rw-r--r--gobject/gvaluecollector.h30
-rw-r--r--gobject/tests/.gitignore1
-rw-r--r--gobject/tests/Makefile.am13
-rw-r--r--gobject/tests/marshalers.list3
-rw-r--r--gobject/tests/signals.c361
13 files changed, 2516 insertions, 191 deletions
diff --git a/gobject/gclosure.c b/gobject/gclosure.c
index 17b7690b2..4cee41cbb 100644
--- a/gobject/gclosure.c
+++ b/gobject/gclosure.c
@@ -34,6 +34,7 @@
#include "genums.h"
#include "gvalue.h"
#include "gvaluetypes.h"
+#include "gtype-private.h"
/**
@@ -90,13 +91,11 @@
* </itemizedlist>
*/
-
#define CLOSURE_MAX_REF_COUNT ((1 << 15) - 1)
#define CLOSURE_MAX_N_GUARDS ((1 << 1) - 1)
#define CLOSURE_MAX_N_FNOTIFIERS ((1 << 2) - 1)
#define CLOSURE_MAX_N_INOTIFIERS ((1 << 8) - 1)
-#define CLOSURE_N_MFUNCS(cl) ((cl)->meta_marshal + \
- ((cl)->n_guards << 1L))
+#define CLOSURE_N_MFUNCS(cl) (((cl)->n_guards << 1L))
/* same as G_CLOSURE_N_NOTIFIERS() (keep in sync) */
#define CLOSURE_N_NOTIFIERS(cl) (CLOSURE_N_MFUNCS (cl) + \
(cl)->n_fnotifiers + \
@@ -198,25 +197,17 @@ GClosure*
g_closure_new_simple (guint sizeof_closure,
gpointer data)
{
+ GRealClosure *real_closure;
GClosure *closure;
g_return_val_if_fail (sizeof_closure >= sizeof (GClosure), NULL);
+ sizeof_closure = sizeof_closure + sizeof (GRealClosure) - sizeof (GClosure);
- closure = g_malloc0 (sizeof_closure);
+ real_closure = g_malloc0 (sizeof_closure);
+ closure = &real_closure->closure;
SET (closure, ref_count, 1);
- SET (closure, meta_marshal, 0);
- SET (closure, n_guards, 0);
- SET (closure, n_fnotifiers, 0);
- SET (closure, n_inotifiers, 0);
- SET (closure, in_inotify, FALSE);
SET (closure, floating, TRUE);
- SET (closure, derivative_flag, 0);
- SET (closure, in_marshal, FALSE);
- SET (closure, is_invalid, FALSE);
- closure->marshal = NULL;
closure->data = data;
- closure->notifiers = NULL;
- memset (G_STRUCT_MEMBER_P (closure, sizeof (*closure)), 0, sizeof_closure - sizeof (*closure));
return closure;
}
@@ -226,10 +217,10 @@ closure_invoke_notifiers (GClosure *closure,
guint notify_type)
{
/* notifier layout:
- * meta_marshal n_guards n_guards n_fnotif. n_inotifiers
- * ->[[meta_marshal][pre_guards][post_guards][fnotifiers][inotifiers]]
+ * n_guards n_guards n_fnotif. n_inotifiers
+ * ->[[pre_guards][post_guards][fnotifiers][inotifiers]]
*
- * CLOSURE_N_MFUNCS(cl) = meta_marshal + n_guards + n_guards;
+ * CLOSURE_N_MFUNCS(cl) = n_guards + n_guards;
* CLOSURE_N_NOTIFIERS(cl) = CLOSURE_N_MFUNCS(cl) + n_fnotifiers + n_inotifiers
*
* constrains/catches:
@@ -239,7 +230,6 @@ closure_invoke_notifiers (GClosure *closure,
* - must prepare for callback removal during FNOTIFY and INOTIFY (done via ->marshal= & ->data=)
* - must distinguish (->marshal= & ->data=) for INOTIFY vs. FNOTIFY (via ->in_inotify)
* + closure->n_guards is const during PRE_NOTIFY & POST_NOTIFY
- * + closure->meta_marshal is const for all cases
* + none of the callbacks can cause recursion
* + closure->n_inotifiers is const 0 during FNOTIFY
*/
@@ -279,7 +269,7 @@ closure_invoke_notifiers (GClosure *closure,
break;
case PRE_NOTIFY:
i = closure->n_guards;
- offs = closure->meta_marshal;
+ offs = 0;
while (i--)
{
ndata = closure->notifiers + offs + i;
@@ -288,7 +278,7 @@ closure_invoke_notifiers (GClosure *closure,
break;
case POST_NOTIFY:
i = closure->n_guards;
- offs = closure->meta_marshal + i;
+ offs = i;
while (i--)
{
ndata = closure->notifiers + offs + i;
@@ -298,6 +288,24 @@ closure_invoke_notifiers (GClosure *closure,
}
}
+static void
+g_closure_set_meta_va_marshal (GClosure *closure,
+ GVaClosureMarshal va_meta_marshal)
+{
+ GRealClosure *real_closure;
+
+ g_return_if_fail (closure != NULL);
+ g_return_if_fail (va_meta_marshal != NULL);
+ g_return_if_fail (closure->is_invalid == FALSE);
+ g_return_if_fail (closure->in_marshal == FALSE);
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ g_return_if_fail (real_closure->meta_marshal != NULL);
+
+ real_closure->va_meta_marshal = va_meta_marshal;
+}
+
/**
* g_closure_set_meta_marshal: (skip)
* @closure: a #GClosure
@@ -325,27 +333,19 @@ g_closure_set_meta_marshal (GClosure *closure,
gpointer marshal_data,
GClosureMarshal meta_marshal)
{
- GClosureNotifyData *notifiers;
+ GRealClosure *real_closure;
g_return_if_fail (closure != NULL);
g_return_if_fail (meta_marshal != NULL);
g_return_if_fail (closure->is_invalid == FALSE);
g_return_if_fail (closure->in_marshal == FALSE);
- g_return_if_fail (closure->meta_marshal == 0);
- notifiers = closure->notifiers;
- closure->notifiers = g_renew (GClosureNotifyData, NULL, CLOSURE_N_NOTIFIERS (closure) + 1);
- if (notifiers)
- {
- /* usually the meta marshal will be setup right after creation, so the
- * g_memmove() should be rare-case scenario
- */
- g_memmove (closure->notifiers + 1, notifiers, CLOSURE_N_NOTIFIERS (closure) * sizeof (notifiers[0]));
- g_free (notifiers);
- }
- closure->notifiers[0].data = marshal_data;
- closure->notifiers[0].notify = (GClosureNotify) meta_marshal;
- SET (closure, meta_marshal, 1);
+ real_closure = G_REAL_CLOSURE (closure);
+
+ g_return_if_fail (real_closure->meta_marshal == NULL);
+
+ real_closure->meta_marshal = meta_marshal;
+ real_closure->meta_marshal_data = marshal_data;
}
/**
@@ -395,14 +395,13 @@ g_closure_add_marshal_guards (GClosure *closure,
closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
closure->n_fnotifiers)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 1];
if (closure->n_guards)
- closure->notifiers[(closure->meta_marshal +
- closure->n_guards +
- closure->n_guards + 1)] = closure->notifiers[closure->meta_marshal + closure->n_guards];
+ closure->notifiers[(closure->n_guards +
+ closure->n_guards + 1)] = closure->notifiers[closure->n_guards];
i = closure->n_guards;
- closure->notifiers[closure->meta_marshal + i].data = pre_marshal_data;
- closure->notifiers[closure->meta_marshal + i].notify = pre_marshal_notify;
- closure->notifiers[closure->meta_marshal + i + 1].data = post_marshal_data;
- closure->notifiers[closure->meta_marshal + i + 1].notify = post_marshal_notify;
+ closure->notifiers[i].data = pre_marshal_data;
+ closure->notifiers[i].notify = pre_marshal_notify;
+ closure->notifiers[i + 1].data = post_marshal_data;
+ closure->notifiers[i + 1].notify = post_marshal_notify;
INC (closure, n_guards);
}
@@ -599,7 +598,7 @@ g_closure_unref (GClosure *closure)
{
closure_invoke_notifiers (closure, FNOTIFY);
g_free (closure->notifiers);
- g_free (closure);
+ g_free (G_REAL_CLOSURE (closure));
}
}
@@ -747,8 +746,12 @@ g_closure_invoke (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint)
{
+ GRealClosure *real_closure;
+
g_return_if_fail (closure != NULL);
+ real_closure = G_REAL_CLOSURE (closure);
+
g_closure_ref (closure); /* preserve floating flag */
if (!closure->is_invalid)
{
@@ -756,13 +759,13 @@ g_closure_invoke (GClosure *closure,
gpointer marshal_data;
gboolean in_marshal = closure->in_marshal;
- g_return_if_fail (closure->marshal || closure->meta_marshal);
+ g_return_if_fail (closure->marshal || real_closure->meta_marshal);
SET (closure, in_marshal, TRUE);
- if (closure->meta_marshal)
+ if (real_closure->meta_marshal)
{
- marshal_data = closure->notifiers[0].data;
- marshal = (GClosureMarshal) closure->notifiers[0].notify;
+ marshal_data = real_closure->meta_marshal_data;
+ marshal = real_closure->meta_marshal;
}
else
{
@@ -783,6 +786,70 @@ g_closure_invoke (GClosure *closure,
g_closure_unref (closure);
}
+gboolean
+_g_closure_supports_invoke_va (GClosure *closure)
+{
+ GRealClosure *real_closure;
+
+ g_return_val_if_fail (closure != NULL, FALSE);
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ return
+ real_closure->va_marshal != NULL &&
+ (real_closure->meta_marshal == NULL ||
+ real_closure->va_meta_marshal != NULL);
+}
+
+void
+_g_closure_invoke_va (GClosure *closure,
+ GValue /*out*/ *return_value,
+ gpointer instance,
+ va_list args,
+ int n_params,
+ GType *param_types)
+{
+ GRealClosure *real_closure;
+
+ g_return_if_fail (closure != NULL);
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ g_closure_ref (closure); /* preserve floating flag */
+ if (!closure->is_invalid)
+ {
+ GVaClosureMarshal marshal;
+ gpointer marshal_data;
+ gboolean in_marshal = closure->in_marshal;
+
+ g_return_if_fail (closure->marshal || real_closure->meta_marshal);
+
+ SET (closure, in_marshal, TRUE);
+ if (real_closure->va_meta_marshal)
+ {
+ marshal_data = real_closure->meta_marshal_data;
+ marshal = real_closure->va_meta_marshal;
+ }
+ else
+ {
+ marshal_data = NULL;
+ marshal = real_closure->va_marshal;
+ }
+ if (!in_marshal)
+ closure_invoke_notifiers (closure, PRE_NOTIFY);
+ marshal (closure,
+ return_value,
+ instance, args,
+ marshal_data,
+ n_params, param_types);
+ if (!in_marshal)
+ closure_invoke_notifiers (closure, POST_NOTIFY);
+ SET (closure, in_marshal, in_marshal);
+ }
+ g_closure_unref (closure);
+}
+
+
/**
* g_closure_set_marshal: (skip)
* @closure: a #GClosure
@@ -809,6 +876,24 @@ g_closure_set_marshal (GClosure *closure,
closure->marshal = marshal;
}
+void
+_g_closure_set_va_marshal (GClosure *closure,
+ GVaClosureMarshal marshal)
+{
+ GRealClosure *real_closure;
+
+ g_return_if_fail (closure != NULL);
+ g_return_if_fail (marshal != NULL);
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ if (real_closure->va_marshal && real_closure->va_marshal != marshal)
+ g_warning ("attempt to override closure->va_marshal (%p) with new marshal (%p)",
+ real_closure->va_marshal, marshal);
+ else
+ real_closure->va_marshal = marshal;
+}
+
/**
* g_cclosure_new: (skip)
* @callback_func: the function to invoke
@@ -890,6 +975,34 @@ g_type_class_meta_marshal (GClosure *closure,
}
static void
+g_type_class_meta_marshalv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ GRealClosure *real_closure;
+ GTypeClass *class;
+ gpointer callback;
+ /* GType itype = (GType) closure->data; */
+ guint offset = GPOINTER_TO_UINT (marshal_data);
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ class = G_TYPE_INSTANCE_GET_CLASS (instance, itype, GTypeClass);
+ callback = G_STRUCT_MEMBER (gpointer, class, offset);
+ if (callback)
+ real_closure->va_marshal (closure,
+ return_value,
+ instance, args,
+ callback,
+ n_params,
+ param_types);
+}
+
+static void
g_type_iface_meta_marshal (GClosure *closure,
GValue /*out*/ *return_value,
guint n_param_values,
@@ -912,6 +1025,70 @@ g_type_iface_meta_marshal (GClosure *closure,
callback);
}
+gboolean
+_g_closure_is_void (GClosure *closure,
+ gpointer instance)
+{
+ GRealClosure *real_closure;
+ GTypeClass *class;
+ gpointer callback;
+ GType itype;
+ guint offset;
+
+ if (closure->is_invalid)
+ return TRUE;
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ if (real_closure->meta_marshal == g_type_iface_meta_marshal)
+ {
+ itype = (GType) closure->data;
+ offset = GPOINTER_TO_UINT (real_closure->meta_marshal_data);
+
+ class = G_TYPE_INSTANCE_GET_INTERFACE (instance, itype, GTypeClass);
+ callback = G_STRUCT_MEMBER (gpointer, class, offset);
+ return callback == NULL;
+ }
+ else if (real_closure->meta_marshal == g_type_class_meta_marshal)
+ {
+ offset = GPOINTER_TO_UINT (real_closure->meta_marshal_data);
+
+ class = G_TYPE_INSTANCE_GET_CLASS (instance, itype, GTypeClass);
+ callback = G_STRUCT_MEMBER (gpointer, class, offset);
+ return callback == NULL;
+ }
+
+ return FALSE;
+}
+
+static void
+g_type_iface_meta_marshalv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ GRealClosure *real_closure;
+ GTypeClass *class;
+ gpointer callback;
+ GType itype = (GType) closure->data;
+ guint offset = GPOINTER_TO_UINT (marshal_data);
+
+ real_closure = G_REAL_CLOSURE (closure);
+
+ class = G_TYPE_INSTANCE_GET_INTERFACE (instance, itype, GTypeClass);
+ callback = G_STRUCT_MEMBER (gpointer, class, offset);
+ if (callback)
+ real_closure->va_marshal (closure,
+ return_value,
+ instance, args,
+ callback,
+ n_params,
+ param_types);
+}
+
/**
* g_signal_type_cclosure_new:
* @itype: the #GType identifier of an interface or classed type
@@ -935,10 +1112,15 @@ g_signal_type_cclosure_new (GType itype,
closure = g_closure_new_simple (sizeof (GClosure), (gpointer) itype);
if (G_TYPE_IS_INTERFACE (itype))
- g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_iface_meta_marshal);
+ {
+ g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_iface_meta_marshal);
+ g_closure_set_meta_va_marshal (closure, g_type_iface_meta_marshalv);
+ }
else
- g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_class_meta_marshal);
-
+ {
+ g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (struct_offset), g_type_class_meta_marshal);
+ g_closure_set_meta_va_marshal (closure, g_type_class_meta_marshalv);
+ }
return closure;
}
@@ -1096,6 +1278,86 @@ value_from_ffi_type (GValue *gvalue, gpointer *value)
}
}
+typedef union {
+ gpointer _gpointer;
+ float _float;
+ double _double;
+ gint _gint;
+ guint _guint;
+ glong _glong;
+ gulong _gulong;
+ gint64 _gint64;
+ guint64 _guint64;
+} va_arg_storage;
+
+static ffi_type *
+va_to_ffi_type (GType gtype,
+ va_list *va,
+ va_arg_storage *storage)
+{
+ ffi_type *rettype = NULL;
+ GType type = g_type_fundamental (gtype);
+ g_assert (type != G_TYPE_INVALID);
+
+ switch (type)
+ {
+ case G_TYPE_BOOLEAN:
+ case G_TYPE_CHAR:
+ case G_TYPE_INT:
+ case G_TYPE_ENUM:
+ rettype = &ffi_type_sint;
+ storage->_gint = va_arg (*va, gint);
+ break;
+ case G_TYPE_UCHAR:
+ case G_TYPE_UINT:
+ case G_TYPE_FLAGS:
+ rettype = &ffi_type_uint;
+ storage->_guint = va_arg (*va, guint);
+ break;
+ case G_TYPE_STRING:
+ case G_TYPE_OBJECT:
+ case G_TYPE_BOXED:
+ case G_TYPE_PARAM:
+ case G_TYPE_POINTER:
+ case G_TYPE_INTERFACE:
+ case G_TYPE_VARIANT:
+ rettype = &ffi_type_pointer;
+ storage->_gpointer = va_arg (*va, gpointer);
+ break;
+ case G_TYPE_FLOAT:
+ /* Float args are passed as doubles in varargs */
+ rettype = &ffi_type_float;
+ storage->_float = (float)va_arg (*va, double);
+ break;
+ case G_TYPE_DOUBLE:
+ rettype = &ffi_type_double;
+ storage->_double = va_arg (*va, double);
+ break;
+ case G_TYPE_LONG:
+ rettype = &ffi_type_slong;
+ storage->_glong = va_arg (*va, glong);
+ break;
+ case G_TYPE_ULONG:
+ rettype = &ffi_type_ulong;
+ storage->_gulong = va_arg (*va, gulong);
+ break;
+ case G_TYPE_INT64:
+ rettype = &ffi_type_sint64;
+ storage->_gint64 = va_arg (*va, gint64);
+ break;
+ case G_TYPE_UINT64:
+ rettype = &ffi_type_uint64;
+ storage->_guint64 = va_arg (*va, guint64);
+ break;
+ default:
+ rettype = &ffi_type_pointer;
+ storage->_guint64 = 0;
+ g_warning ("va_to_ffi_type: Unsupported fundamental type: %s", g_type_name (type));
+ break;
+ }
+ return rettype;
+}
+
/**
* g_cclosure_marshal_generic:
* @closure: A #GClosure.
@@ -1192,6 +1454,123 @@ g_cclosure_marshal_generic (GClosure *closure,
value_from_ffi_type (return_gvalue, rvalue);
}
+void
+g_cclosure_marshal_generic_va (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args_list,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ ffi_type *rtype;
+ void *rvalue;
+ int n_args;
+ ffi_type **atypes;
+ void **args;
+ va_arg_storage *storage;
+ int i;
+ ffi_cif cif;
+ GCClosure *cc = (GCClosure*) closure;
+ gint *enum_tmpval;
+ gboolean tmpval_used = FALSE;
+ va_list args_copy;
+
+ enum_tmpval = g_alloca (sizeof (gint));
+ if (return_value && G_VALUE_TYPE (return_value))
+ {
+ rtype = value_to_ffi_type (return_value, &rvalue, enum_tmpval, &tmpval_used);
+ }
+ else
+ {
+ rtype = &ffi_type_void;
+ }
+
+ rvalue = g_alloca (MAX (rtype->size, sizeof (ffi_arg)));
+
+ n_args = n_params + 2;
+ atypes = g_alloca (sizeof (ffi_type *) * n_args);
+ args = g_alloca (sizeof (gpointer) * n_args);
+ storage = g_alloca (sizeof (va_arg_storage) * n_params);
+
+ if (tmpval_used)
+ enum_tmpval = g_alloca (sizeof (gint));
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ atypes[n_args-1] = &ffi_type_pointer;
+ args[n_args-1] = &instance;
+ atypes[0] = &ffi_type_pointer;
+ args[0] = &closure->data;
+ }
+ else
+ {
+ atypes[0] = &ffi_type_pointer;
+ args[0] = &instance;
+ atypes[n_args-1] = &ffi_type_pointer;
+ args[n_args-1] = &closure->data;
+ }
+
+ va_copy (args_copy, args_list);
+
+ /* Box non-primitive arguments */
+ for (i = 0; i < n_params; i++)
+ {
+ GType type = param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
+ GType fundamental = G_TYPE_FUNDAMENTAL (type);
+
+ atypes[i+1] = va_to_ffi_type (type,
+ &args_copy,
+ &storage[i]);
+ args[i+1] = &storage[i];
+
+ if ((param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0)
+ {
+ if (fundamental == G_TYPE_STRING && storage[i]._gpointer != NULL)
+ storage[i]._gpointer = g_strdup (storage[i]._gpointer);
+ else if (fundamental == G_TYPE_PARAM && storage[i]._gpointer != NULL)
+ storage[i]._gpointer = g_param_spec_ref (storage[i]._gpointer);
+ else if (fundamental == G_TYPE_BOXED && storage[i]._gpointer != NULL)
+ storage[i]._gpointer = g_boxed_copy (type, storage[i]._gpointer);
+ else if (fundamental == G_TYPE_VARIANT && storage[i]._gpointer != NULL)
+ storage[i]._gpointer = g_variant_ref_sink (storage[i]._gpointer);
+ }
+ if (fundamental == G_TYPE_OBJECT && storage[i]._gpointer != NULL)
+ storage[i]._gpointer = g_object_ref (storage[i]._gpointer);
+ }
+
+ va_end (args_copy);
+
+ if (ffi_prep_cif (&cif, FFI_DEFAULT_ABI, n_args, rtype, atypes) != FFI_OK)
+ return;
+
+ ffi_call (&cif, marshal_data ? marshal_data : cc->callback, rvalue, args);
+
+ /* Unbox non-primitive arguments */
+ for (i = 0; i < n_params; i++)
+ {
+ GType type = param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
+ GType fundamental = G_TYPE_FUNDAMENTAL (type);
+
+ if ((param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0)
+ {
+ if (fundamental == G_TYPE_STRING && storage[i]._gpointer != NULL)
+ g_free (storage[i]._gpointer);
+ else if (fundamental == G_TYPE_PARAM && storage[i]._gpointer != NULL)
+ g_param_spec_unref (storage[i]._gpointer);
+ else if (fundamental == G_TYPE_BOXED && storage[i]._gpointer != NULL)
+ g_boxed_free (type, storage[i]._gpointer);
+ else if (fundamental == G_TYPE_VARIANT && storage[i]._gpointer != NULL)
+ g_variant_unref (storage[i]._gpointer);
+ }
+ if (fundamental == G_TYPE_OBJECT && storage[i]._gpointer != NULL)
+ g_object_unref (storage[i]._gpointer);
+ }
+
+ if (return_value && G_VALUE_TYPE (return_value))
+ value_from_ffi_type (return_value, rvalue);
+}
+
/**
* g_cclosure_marshal_VOID__VOID:
* @closure: the #GClosure to which the marshaller belongs
diff --git a/gobject/gclosure.h b/gobject/gclosure.h
index bb024a44f..fffac5824 100644
--- a/gobject/gclosure.h
+++ b/gobject/gclosure.h
@@ -51,7 +51,7 @@ G_BEGIN_DECLS
*
* Returns: number of notifiers
*/
-#define G_CLOSURE_N_NOTIFIERS(cl) ((cl)->meta_marshal + ((cl)->n_guards << 1L) + \
+#define G_CLOSURE_N_NOTIFIERS(cl) (((cl)->n_guards << 1L) + \
(cl)->n_fnotifiers + (cl)->n_inotifiers)
/**
* G_CCLOSURE_SWAP_DATA:
@@ -120,6 +120,15 @@ typedef void (*GClosureMarshal) (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+
+typedef void (* GVaClosureMarshal) (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
+
/**
* GCClosure:
* @closure: the #GClosure
@@ -149,7 +158,9 @@ struct _GClosure
{
/*< private >*/
volatile guint ref_count : 15;
- volatile guint meta_marshal : 1;
+ /* meta_marshal is not used anymore but must be zero for historical reasons
+ as it was exposed in the G_CLOSURE_N_NOTIFIERS macro */
+ volatile guint meta_marshal_nouse : 1;
volatile guint n_guards : 1;
volatile guint n_fnotifiers : 2; /* finalization notifiers */
volatile guint n_inotifiers : 8; /* invalidation notifiers */
@@ -256,6 +267,15 @@ void g_cclosure_marshal_generic (GClosure *closure,
gpointer invocation_hint,
gpointer marshal_data);
+void g_cclosure_marshal_generic_va (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args_list,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
+
+
G_END_DECLS
#endif /* __G_CLOSURE_H__ */
diff --git a/gobject/glib-genmarshal.c b/gobject/glib-genmarshal.c
index d79ae798a..2283b26c1 100644
--- a/gobject/glib-genmarshal.c
+++ b/gobject/glib-genmarshal.c
@@ -50,7 +50,12 @@ typedef struct
gchar *keyword; /* marhaller list keyword [MY_STRING] */
const gchar *sig_name; /* signature name [STRING] */
const gchar *ctype; /* C type name [gchar*] */
+ const gchar *promoted_ctype; /* promoted C type name [gchar*] */
const gchar *getter; /* value getter function [g_value_get_string] */
+ const gchar *box; /* value box function [g_strdup] */
+ const gchar *unbox; /* value unbox function [g_free] */
+ gboolean box_ignores_static; /* Wether the box/unbox functions ignore the static_scope */
+ gboolean box_takes_type; /* Wether the box/unbox functions take a type arg */
} InArgument;
typedef struct
{
@@ -122,6 +127,7 @@ static FILE *fout = NULL;
static gboolean gen_cheader = FALSE;
static gboolean gen_cbody = FALSE;
static gboolean gen_internal = FALSE;
+static gboolean gen_valist = FALSE;
static gboolean skip_ploc = FALSE;
static gboolean std_includes = TRUE;
static gint exit_status = 0;
@@ -184,30 +190,30 @@ static gboolean
complete_in_arg (InArgument *iarg)
{
static const InArgument args[] = {
- /* keyword sig_name ctype getter */
- { "VOID", "VOID", "void", NULL, },
- { "BOOLEAN", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", },
- { "CHAR", "CHAR", "gchar", "g_marshal_value_peek_char", },
- { "UCHAR", "UCHAR", "guchar", "g_marshal_value_peek_uchar", },
- { "INT", "INT", "gint", "g_marshal_value_peek_int", },
- { "UINT", "UINT", "guint", "g_marshal_value_peek_uint", },
- { "LONG", "LONG", "glong", "g_marshal_value_peek_long", },
- { "ULONG", "ULONG", "gulong", "g_marshal_value_peek_ulong", },
- { "INT64", "INT64", "gint64", "g_marshal_value_peek_int64", },
- { "UINT64", "UINT64", "guint64", "g_marshal_value_peek_uint64", },
- { "ENUM", "ENUM", "gint", "g_marshal_value_peek_enum", },
- { "FLAGS", "FLAGS", "guint", "g_marshal_value_peek_flags", },
- { "FLOAT", "FLOAT", "gfloat", "g_marshal_value_peek_float", },
- { "DOUBLE", "DOUBLE", "gdouble", "g_marshal_value_peek_double", },
- { "STRING", "STRING", "gpointer", "g_marshal_value_peek_string", },
- { "PARAM", "PARAM", "gpointer", "g_marshal_value_peek_param", },
- { "BOXED", "BOXED", "gpointer", "g_marshal_value_peek_boxed", },
- { "POINTER", "POINTER", "gpointer", "g_marshal_value_peek_pointer", },
- { "OBJECT", "OBJECT", "gpointer", "g_marshal_value_peek_object", },
- { "VARIANT", "VARIANT", "gpointer", "g_marshal_value_peek_variant", },
+ /* keyword sig_name ctype promoted getter */
+ { "VOID", "VOID", "void", "void", NULL, },
+ { "BOOLEAN", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
+ { "CHAR", "CHAR", "gchar", "gint", "g_marshal_value_peek_char", },
+ { "UCHAR", "UCHAR", "guchar", "guint", "g_marshal_value_peek_uchar", },
+ { "INT", "INT", "gint", "gint", "g_marshal_value_peek_int", },
+ { "UINT", "UINT", "guint", "guint", "g_marshal_value_peek_uint", },
+ { "LONG", "LONG", "glong", "glong", "g_marshal_value_peek_long", },
+ { "ULONG", "ULONG", "gulong", "gulong", "g_marshal_value_peek_ulong", },
+ { "INT64", "INT64", "gint64", "gint64", "g_marshal_value_peek_int64", },
+ { "UINT64", "UINT64", "guint64", "guint64", "g_marshal_value_peek_uint64", },
+ { "ENUM", "ENUM", "gint", "gint", "g_marshal_value_peek_enum", },
+ { "FLAGS", "FLAGS", "guint", "guint", "g_marshal_value_peek_flags", },
+ { "FLOAT", "FLOAT", "gfloat", "gdouble", "g_marshal_value_peek_float", },
+ { "DOUBLE", "DOUBLE", "gdouble", "gdouble", "g_marshal_value_peek_double", },
+ { "STRING", "STRING", "gpointer", "gpointer", "g_marshal_value_peek_string", "g_strdup", "g_free"},
+ { "PARAM", "PARAM", "gpointer", "gpointer", "g_marshal_value_peek_param", "g_param_spec_ref", "g_param_spec_unref"},
+ { "BOXED", "BOXED", "gpointer", "gpointer", "g_marshal_value_peek_boxed", "g_boxed_copy", "g_boxed_free", FALSE, TRUE},
+ { "POINTER", "POINTER", "gpointer", "gpointer", "g_marshal_value_peek_pointer", },
+ { "OBJECT", "OBJECT", "gpointer", "gpointer", "g_marshal_value_peek_object", "g_object_ref", "g_object_unref", TRUE},
+ { "VARIANT", "VARIANT", "gpointer", "gpointer", "g_marshal_value_peek_variant", "g_variant_ref_sink", "g_variant_unref"},
/* deprecated: */
- { "NONE", "VOID", "void", NULL, },
- { "BOOL", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", },
+ { "NONE", "VOID", "void", "void", NULL, },
+ { "BOOL", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
};
guint i;
@@ -218,7 +224,12 @@ complete_in_arg (InArgument *iarg)
{
iarg->sig_name = args[i].sig_name;
iarg->ctype = args[i].ctype;
+ iarg->promoted_ctype = args[i].promoted_ctype;
iarg->getter = args[i].getter;
+ iarg->box = args[i].box;
+ iarg->unbox = args[i].unbox;
+ iarg->box_ignores_static = args[i].box_ignores_static;
+ iarg->box_takes_type = args[i].box_takes_type;
return TRUE;
}
@@ -357,6 +368,7 @@ generate_marshal (const gchar *signame,
g_free (tmp);
}
+ /* GValue marshaller */
if (gen_cheader && have_std_marshaller)
{
g_fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, signame, std_marshaller_prefix, signame);
@@ -459,6 +471,174 @@ generate_marshal (const gchar *signame,
/* cfile marshal footer */
g_fprintf (fout, "}\n");
}
+
+
+ /* vararg marshaller */
+ if (gen_cheader && gen_valist && have_std_marshaller)
+ {
+ g_fprintf (fout, "#define %s_%sv\t%s_%sv\n", marshaller_prefix, signame, std_marshaller_prefix, signame);
+ }
+ if (gen_cheader && gen_valist && !have_std_marshaller)
+ {
+ ind = g_fprintf (fout, gen_internal ? "G_GNUC_INTERNAL " : "extern ");
+ ind += g_fprintf (fout, "void ");
+ ind += g_fprintf (fout, "%s_%sv (", marshaller_prefix, signame);
+ g_fprintf (fout, "GClosure *closure,\n");
+ g_fprintf (fout, "%sGValue *return_value,\n", indent (ind));
+ g_fprintf (fout, "%sgpointer instance,\n", indent (ind));
+ g_fprintf (fout, "%sva_list args,\n", indent (ind));
+ g_fprintf (fout, "%sgpointer marshal_data,\n", indent (ind));
+ g_fprintf (fout, "%sint n_params,\n", indent (ind));
+ g_fprintf (fout, "%sGType *param_types);\n", indent (ind));
+ }
+ if (gen_cbody && gen_valist && !have_std_marshaller)
+ {
+ gint i;
+ gboolean has_arg;
+
+ g_fprintf (fout, "void\n");
+ ind = g_fprintf (fout, "%s_%sv (", marshaller_prefix, signame);
+ g_fprintf (fout, "GClosure *closure,\n");
+ g_fprintf (fout, "%sGValue *return_value,\n", indent (ind));
+ g_fprintf (fout, "%sgpointer instance,\n", indent (ind));
+ g_fprintf (fout, "%sva_list args,\n", indent (ind));
+ g_fprintf (fout, "%sgpointer marshal_data,\n", indent (ind));
+ g_fprintf (fout, "%sint n_params,\n", indent (ind));
+ g_fprintf (fout, "%sGType *param_types)\n", indent (ind));
+ g_fprintf (fout, "{\n");
+
+ ind = g_fprintf (fout, " typedef %s (*GMarshalFunc_%s) (", sig->rarg->ctype, signame);
+ g_fprintf (fout, "%s instance", pad ("gpointer"));
+ for (a = 0, node = sig->args; node; node = node->next)
+ {
+ InArgument *iarg = node->data;
+
+ if (iarg->getter)
+ g_fprintf (fout, ",\n%s%s arg_%d", indent (ind), pad (iarg->ctype), a++);
+ }
+ g_fprintf (fout, ",\n%s%s data);\n", indent (ind), pad ("gpointer"));
+ g_fprintf (fout, " GCClosure *cc = (GCClosure*) closure;\n");
+ g_fprintf (fout, " gpointer data1, data2;\n");
+ g_fprintf (fout, " GMarshalFunc_%s callback;\n", signame);
+ has_arg = FALSE;
+
+ i = 0;
+ for (node = sig->args; node; node = node->next)
+ {
+ InArgument *iarg = node->data;
+
+ if (iarg->getter)
+ {
+ g_fprintf (fout, " %s arg%i;\n", iarg->ctype, i++);
+ has_arg = TRUE;
+ }
+ }
+ if (has_arg)
+ g_fprintf (fout, " va_list args_copy;\n");
+
+ if (sig->rarg->setter)
+ g_fprintf (fout, " %s v_return;\n", sig->rarg->ctype);
+
+ if (sig->rarg->setter)
+ {
+ g_fprintf (fout, "\n");
+ g_fprintf (fout, " g_return_if_fail (return_value != NULL);\n");
+ }
+
+ /* cfile marshal data1, data2 and callback setup */
+ if (has_arg)
+ {
+ g_fprintf (fout, "\n");
+ g_fprintf (fout, " va_copy (args_copy, args);\n");
+ i = 0;
+ for (node = sig->args; node; node = node->next)
+ {
+ InArgument *iarg = node->data;
+
+ if (iarg->getter)
+ {
+ g_fprintf (fout, " arg%i = (%s) va_arg (args_copy, %s);\n",
+ i, iarg->ctype, iarg->promoted_ctype);
+
+ if (iarg->box != NULL)
+ {
+ g_fprintf (fout, " if (");
+ if (!iarg->box_ignores_static)
+ g_fprintf (fout, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i);
+ g_fprintf (fout, "arg%i != NULL)\n ", i);
+ if (iarg->box_takes_type)
+ g_fprintf (fout,
+ " arg%i = %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
+ i, iarg->box, i, i);
+ else
+ g_fprintf (fout,
+ " arg%i = %s (arg%i);\n",
+ i, iarg->box, i);
+ }
+ }
+ i++;
+ }
+ g_fprintf (fout, " va_end (args_copy);\n");
+ }
+
+ g_fprintf (fout, "\n");
+ /* cfile marshal data1, data2 and callback setup */
+ g_fprintf (fout, " if (G_CCLOSURE_SWAP_DATA (closure))\n {\n");
+ g_fprintf (fout, " data1 = closure->data;\n");
+ g_fprintf (fout, " data2 = instance;\n");
+ g_fprintf (fout, " }\n else\n {\n");
+ g_fprintf (fout, " data1 = instance;\n");
+ g_fprintf (fout, " data2 = closure->data;\n");
+ g_fprintf (fout, " }\n");
+ g_fprintf (fout, " callback = (GMarshalFunc_%s) (marshal_data ? marshal_data : cc->callback);\n", signame);
+
+ /* cfile marshal callback action */
+ g_fprintf (fout, "\n");
+ ind = g_fprintf (fout, " %s callback (", sig->rarg->setter ? " v_return =" : "");
+ g_fprintf (fout, "data1");
+
+ i = 0;
+ for (node = sig->args; node; node = node->next)
+ {
+ InArgument *iarg = node->data;
+
+ if (iarg->getter)
+ g_fprintf (fout, ",\n%sarg%i", indent (ind), i++);
+ }
+ g_fprintf (fout, ",\n%sdata2);\n", indent (ind));
+
+ i = 0;
+ for (node = sig->args; node; node = node->next)
+ {
+ InArgument *iarg = node->data;
+
+ if (iarg->unbox)
+ {
+ g_fprintf (fout, " if (");
+ if (!iarg->box_ignores_static)
+ g_fprintf (fout, "(param_types[%i] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && ", i);
+ g_fprintf (fout, "arg%i != NULL)\n ", i);
+ if (iarg->box_takes_type)
+ g_fprintf (fout,
+ " %s (param_types[%i] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg%i);\n",
+ iarg->unbox, i, i);
+ else
+ g_fprintf (fout,
+ " %s (arg%i);\n",
+ iarg->unbox, i);
+ }
+ i++;
+ }
+
+ /* cfile marshal return value storage */
+ if (sig->rarg->setter)
+ {
+ g_fprintf (fout, "\n");
+ g_fprintf (fout, " %s (return_value, v_return);\n", sig->rarg->setter);
+ }
+
+ g_fprintf (fout, "}\n\n");
+ }
}
static void
@@ -802,6 +982,11 @@ parse_args (gint *argc_p,
gen_internal = TRUE;
argv[i] = NULL;
}
+ else if (strcmp ("--valist-marshallers", argv[i]) == 0)
+ {
+ gen_valist = TRUE;
+ argv[i] = NULL;
+ }
else if ((strcmp ("--prefix", argv[i]) == 0) ||
(strncmp ("--prefix=", argv[i], 9) == 0))
{
@@ -890,6 +1075,7 @@ print_blurb (FILE *bout,
g_fprintf (bout, " --skip-source Skip source location comments\n");
g_fprintf (bout, " --stdinc, --nostdinc Include/use standard marshallers\n");
g_fprintf (bout, " --internal Mark generated functions as internal\n");
+ g_fprintf (bout, " --valist-marshallers Generate va_list marshallers\n");
g_fprintf (bout, " -v, --version Print version informations\n");
g_fprintf (bout, " --g-fatal-warnings Make warnings fatal (abort)\n");
}
diff --git a/gobject/gmarshal.c b/gobject/gmarshal.c
index c7bcce45b..ce029ca58 100644
--- a/gobject/gmarshal.c
+++ b/gobject/gmarshal.c
@@ -85,6 +85,37 @@ g_cclosure_marshal_VOID__VOID (GClosure *closure,
callback (data1,
data2);
}
+void
+g_cclosure_marshal_VOID__VOIDv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__VOID) (gpointer instance,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__VOID callback;
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__VOID) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ data2);
+}
+
/* VOID:BOOLEAN (./gmarshal.list:7) */
void
@@ -120,6 +151,45 @@ g_cclosure_marshal_VOID__BOOLEAN (GClosure *closure,
g_marshal_value_peek_boolean (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__BOOLEANv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__BOOLEAN) (gpointer instance,
+ gboolean arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__BOOLEAN callback;
+ gboolean arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gboolean) va_arg (args_copy, gboolean);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__BOOLEAN) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:CHAR (./gmarshal.list:8) */
void
@@ -155,6 +225,45 @@ g_cclosure_marshal_VOID__CHAR (GClosure *closure,
g_marshal_value_peek_char (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__CHARv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__CHAR) (gpointer instance,
+ gchar arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__CHAR callback;
+ gchar arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gchar) va_arg (args_copy, gint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__CHAR) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:UCHAR (./gmarshal.list:9) */
void
@@ -190,6 +299,45 @@ g_cclosure_marshal_VOID__UCHAR (GClosure *closure,
g_marshal_value_peek_uchar (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__UCHARv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__UCHAR) (gpointer instance,
+ guchar arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__UCHAR callback;
+ guchar arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (guchar) va_arg (args_copy, guint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__UCHAR) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:INT (./gmarshal.list:10) */
void
@@ -225,6 +373,45 @@ g_cclosure_marshal_VOID__INT (GClosure *closure,
g_marshal_value_peek_int (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__INTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__INT) (gpointer instance,
+ gint arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__INT callback;
+ gint arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gint) va_arg (args_copy, gint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:UINT (./gmarshal.list:11) */
void
@@ -260,6 +447,45 @@ g_cclosure_marshal_VOID__UINT (GClosure *closure,
g_marshal_value_peek_uint (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__UINTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__UINT) (gpointer instance,
+ guint arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__UINT callback;
+ guint arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (guint) va_arg (args_copy, guint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__UINT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:LONG (./gmarshal.list:12) */
void
@@ -295,6 +521,45 @@ g_cclosure_marshal_VOID__LONG (GClosure *closure,
g_marshal_value_peek_long (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__LONGv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__LONG) (gpointer instance,
+ glong arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__LONG callback;
+ glong arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (glong) va_arg (args_copy, glong);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__LONG) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:ULONG (./gmarshal.list:13) */
void
@@ -330,6 +595,45 @@ g_cclosure_marshal_VOID__ULONG (GClosure *closure,
g_marshal_value_peek_ulong (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__ULONGv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__ULONG) (gpointer instance,
+ gulong arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__ULONG callback;
+ gulong arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gulong) va_arg (args_copy, gulong);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__ULONG) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:ENUM (./gmarshal.list:14) */
void
@@ -365,6 +669,45 @@ g_cclosure_marshal_VOID__ENUM (GClosure *closure,
g_marshal_value_peek_enum (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__ENUMv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__ENUM) (gpointer instance,
+ gint arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__ENUM callback;
+ gint arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gint) va_arg (args_copy, gint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__ENUM) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:FLAGS (./gmarshal.list:15) */
void
@@ -400,6 +743,45 @@ g_cclosure_marshal_VOID__FLAGS (GClosure *closure,
g_marshal_value_peek_flags (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__FLAGSv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__FLAGS) (gpointer instance,
+ guint arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__FLAGS callback;
+ guint arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (guint) va_arg (args_copy, guint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__FLAGS) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:FLOAT (./gmarshal.list:16) */
void
@@ -435,6 +817,45 @@ g_cclosure_marshal_VOID__FLOAT (GClosure *closure,
g_marshal_value_peek_float (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__FLOATv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__FLOAT) (gpointer instance,
+ gfloat arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__FLOAT callback;
+ gfloat arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gfloat) va_arg (args_copy, gdouble);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__FLOAT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:DOUBLE (./gmarshal.list:17) */
void
@@ -470,6 +891,45 @@ g_cclosure_marshal_VOID__DOUBLE (GClosure *closure,
g_marshal_value_peek_double (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__DOUBLEv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__DOUBLE) (gpointer instance,
+ gdouble arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__DOUBLE callback;
+ gdouble arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gdouble) va_arg (args_copy, gdouble);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__DOUBLE) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:STRING (./gmarshal.list:18) */
void
@@ -505,6 +965,49 @@ g_cclosure_marshal_VOID__STRING (GClosure *closure,
g_marshal_value_peek_string (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__STRINGv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__STRING) (gpointer instance,
+ gpointer arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__STRING callback;
+ gpointer arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ arg0 = g_strdup (arg0);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ g_free (arg0);
+}
+
/* VOID:PARAM (./gmarshal.list:19) */
void
@@ -540,6 +1043,49 @@ g_cclosure_marshal_VOID__PARAM (GClosure *closure,
g_marshal_value_peek_param (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__PARAMv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__PARAM) (gpointer instance,
+ gpointer arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__PARAM callback;
+ gpointer arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ arg0 = g_param_spec_ref (arg0);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__PARAM) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ g_param_spec_unref (arg0);
+}
+
/* VOID:BOXED (./gmarshal.list:20) */
void
@@ -575,6 +1121,49 @@ g_cclosure_marshal_VOID__BOXED (GClosure *closure,
g_marshal_value_peek_boxed (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__BOXEDv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__BOXED) (gpointer instance,
+ gpointer arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__BOXED callback;
+ gpointer arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ arg0 = g_boxed_copy (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg0);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__BOXED) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ g_boxed_free (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg0);
+}
+
/* VOID:POINTER (./gmarshal.list:21) */
void
@@ -610,6 +1199,45 @@ g_cclosure_marshal_VOID__POINTER (GClosure *closure,
g_marshal_value_peek_pointer (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__POINTERv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__POINTER) (gpointer instance,
+ gpointer arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__POINTER callback;
+ gpointer arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+}
+
/* VOID:OBJECT (./gmarshal.list:22) */
void
@@ -645,6 +1273,49 @@ g_cclosure_marshal_VOID__OBJECT (GClosure *closure,
g_marshal_value_peek_object (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__OBJECTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__OBJECT) (gpointer instance,
+ gpointer arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__OBJECT callback;
+ gpointer arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if (arg0 != NULL)
+ arg0 = g_object_ref (arg0);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+ if (arg0 != NULL)
+ g_object_unref (arg0);
+}
+
/* VOID:VARIANT (./gmarshal.list:23) */
void
@@ -680,6 +1351,49 @@ g_cclosure_marshal_VOID__VARIANT (GClosure *closure,
g_marshal_value_peek_variant (param_values + 1),
data2);
}
+void
+g_cclosure_marshal_VOID__VARIANTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__VARIANT) (gpointer instance,
+ gpointer arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__VARIANT callback;
+ gpointer arg0;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ arg0 = g_variant_ref_sink (arg0);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__VARIANT) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ data2);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ g_variant_unref (arg0);
+}
+
/* VOID:UINT,POINTER (./gmarshal.list:26) */
void
@@ -717,6 +1431,49 @@ g_cclosure_marshal_VOID__UINT_POINTER (GClosure *closure,
g_marshal_value_peek_pointer (param_values + 2),
data2);
}
+void
+g_cclosure_marshal_VOID__UINT_POINTERv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef void (*GMarshalFunc_VOID__UINT_POINTER) (gpointer instance,
+ guint arg_0,
+ gpointer arg_1,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_VOID__UINT_POINTER callback;
+ guint arg0;
+ gpointer arg1;
+ va_list args_copy;
+
+ va_copy (args_copy, args);
+ arg0 = (guint) va_arg (args_copy, guint);
+ arg1 = (gpointer) va_arg (args_copy, gpointer);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__UINT_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ arg0,
+ arg1,
+ data2);
+}
+
/* BOOL:FLAGS (./gmarshal.list:27) */
void
@@ -756,6 +1513,50 @@ g_cclosure_marshal_BOOLEAN__FLAGS (GClosure *closure,
g_value_set_boolean (return_value, v_return);
}
+void
+g_cclosure_marshal_BOOLEAN__FLAGSv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__FLAGS) (gpointer instance,
+ guint arg_0,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_BOOLEAN__FLAGS callback;
+ guint arg0;
+ va_list args_copy;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+
+ va_copy (args_copy, args);
+ arg0 = (guint) va_arg (args_copy, guint);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__FLAGS) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ arg0,
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
/* STRING:OBJECT,POINTER (./gmarshal.list:28) */
void
@@ -797,6 +1598,58 @@ g_cclosure_marshal_STRING__OBJECT_POINTER (GClosure *closure,
g_value_take_string (return_value, v_return);
}
+void
+g_cclosure_marshal_STRING__OBJECT_POINTERv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef gchar* (*GMarshalFunc_STRING__OBJECT_POINTER) (gpointer instance,
+ gpointer arg_0,
+ gpointer arg_1,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_STRING__OBJECT_POINTER callback;
+ gpointer arg0;
+ gpointer arg1;
+ va_list args_copy;
+ gchar* v_return;
+
+ g_return_if_fail (return_value != NULL);
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if (arg0 != NULL)
+ arg0 = g_object_ref (arg0);
+ arg1 = (gpointer) va_arg (args_copy, gpointer);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_STRING__OBJECT_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ arg0,
+ arg1,
+ data2);
+ if (arg0 != NULL)
+ g_object_unref (arg0);
+
+ g_value_take_string (return_value, v_return);
+}
+
/* BOOL:BOXED,BOXED (./gmarshal.list:29) */
void
@@ -838,4 +1691,60 @@ g_cclosure_marshal_BOOLEAN__BOXED_BOXED (GClosure *closure,
g_value_set_boolean (return_value, v_return);
}
+void
+g_cclosure_marshal_BOOLEAN__BOXED_BOXEDv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__BOXED_BOXED) (gpointer instance,
+ gpointer arg_0,
+ gpointer arg_1,
+ gpointer data);
+ GCClosure *cc = (GCClosure*) closure;
+ gpointer data1, data2;
+ GMarshalFunc_BOOLEAN__BOXED_BOXED callback;
+ gpointer arg0;
+ gpointer arg1;
+ va_list args_copy;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+
+ va_copy (args_copy, args);
+ arg0 = (gpointer) va_arg (args_copy, gpointer);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ arg0 = g_boxed_copy (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg0);
+ arg1 = (gpointer) va_arg (args_copy, gpointer);
+ if ((param_types[1] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg1 != NULL)
+ arg1 = g_boxed_copy (param_types[1] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg1);
+ va_end (args_copy);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = instance;
+ }
+ else
+ {
+ data1 = instance;
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__BOXED_BOXED) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ arg0,
+ arg1,
+ data2);
+ if ((param_types[0] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg0 != NULL)
+ g_boxed_free (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg0);
+ if ((param_types[1] & G_SIGNAL_TYPE_STATIC_SCOPE) == 0 && arg1 != NULL)
+ g_boxed_free (param_types[1] & ~G_SIGNAL_TYPE_STATIC_SCOPE, arg1);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
diff --git a/gobject/gmarshal.h b/gobject/gmarshal.h
index 1238c0227..0c21be687 100644
--- a/gobject/gmarshal.h
+++ b/gobject/gmarshal.h
@@ -11,6 +11,13 @@ extern void g_cclosure_marshal_VOID__VOID (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__VOIDv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:BOOLEAN (./gmarshal.list:7) */
extern void g_cclosure_marshal_VOID__BOOLEAN (GClosure *closure,
@@ -19,6 +26,13 @@ extern void g_cclosure_marshal_VOID__BOOLEAN (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__BOOLEANv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:CHAR (./gmarshal.list:8) */
extern void g_cclosure_marshal_VOID__CHAR (GClosure *closure,
@@ -27,6 +41,13 @@ extern void g_cclosure_marshal_VOID__CHAR (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__CHARv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:UCHAR (./gmarshal.list:9) */
extern void g_cclosure_marshal_VOID__UCHAR (GClosure *closure,
@@ -35,6 +56,13 @@ extern void g_cclosure_marshal_VOID__UCHAR (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__UCHARv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:INT (./gmarshal.list:10) */
extern void g_cclosure_marshal_VOID__INT (GClosure *closure,
@@ -43,6 +71,13 @@ extern void g_cclosure_marshal_VOID__INT (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__INTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:UINT (./gmarshal.list:11) */
extern void g_cclosure_marshal_VOID__UINT (GClosure *closure,
@@ -51,6 +86,13 @@ extern void g_cclosure_marshal_VOID__UINT (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__UINTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:LONG (./gmarshal.list:12) */
extern void g_cclosure_marshal_VOID__LONG (GClosure *closure,
@@ -59,6 +101,13 @@ extern void g_cclosure_marshal_VOID__LONG (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__LONGv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:ULONG (./gmarshal.list:13) */
extern void g_cclosure_marshal_VOID__ULONG (GClosure *closure,
@@ -67,6 +116,13 @@ extern void g_cclosure_marshal_VOID__ULONG (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__ULONGv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:ENUM (./gmarshal.list:14) */
extern void g_cclosure_marshal_VOID__ENUM (GClosure *closure,
@@ -75,6 +131,13 @@ extern void g_cclosure_marshal_VOID__ENUM (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__ENUMv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:FLAGS (./gmarshal.list:15) */
extern void g_cclosure_marshal_VOID__FLAGS (GClosure *closure,
@@ -83,6 +146,13 @@ extern void g_cclosure_marshal_VOID__FLAGS (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__FLAGSv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:FLOAT (./gmarshal.list:16) */
extern void g_cclosure_marshal_VOID__FLOAT (GClosure *closure,
@@ -91,6 +161,13 @@ extern void g_cclosure_marshal_VOID__FLOAT (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__FLOATv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:DOUBLE (./gmarshal.list:17) */
extern void g_cclosure_marshal_VOID__DOUBLE (GClosure *closure,
@@ -99,6 +176,13 @@ extern void g_cclosure_marshal_VOID__DOUBLE (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__DOUBLEv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:STRING (./gmarshal.list:18) */
extern void g_cclosure_marshal_VOID__STRING (GClosure *closure,
@@ -107,6 +191,13 @@ extern void g_cclosure_marshal_VOID__STRING (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__STRINGv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:PARAM (./gmarshal.list:19) */
extern void g_cclosure_marshal_VOID__PARAM (GClosure *closure,
@@ -115,6 +206,13 @@ extern void g_cclosure_marshal_VOID__PARAM (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__PARAMv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:BOXED (./gmarshal.list:20) */
extern void g_cclosure_marshal_VOID__BOXED (GClosure *closure,
@@ -123,6 +221,13 @@ extern void g_cclosure_marshal_VOID__BOXED (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__BOXEDv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:POINTER (./gmarshal.list:21) */
extern void g_cclosure_marshal_VOID__POINTER (GClosure *closure,
@@ -131,6 +236,13 @@ extern void g_cclosure_marshal_VOID__POINTER (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__POINTERv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:OBJECT (./gmarshal.list:22) */
extern void g_cclosure_marshal_VOID__OBJECT (GClosure *closure,
@@ -139,6 +251,13 @@ extern void g_cclosure_marshal_VOID__OBJECT (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__OBJECTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:VARIANT (./gmarshal.list:23) */
extern void g_cclosure_marshal_VOID__VARIANT (GClosure *closure,
@@ -147,6 +266,13 @@ extern void g_cclosure_marshal_VOID__VARIANT (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__VARIANTv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* VOID:UINT,POINTER (./gmarshal.list:26) */
extern void g_cclosure_marshal_VOID__UINT_POINTER (GClosure *closure,
@@ -155,6 +281,13 @@ extern void g_cclosure_marshal_VOID__UINT_POINTER (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_VOID__UINT_POINTERv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* BOOL:FLAGS (./gmarshal.list:27) */
extern void g_cclosure_marshal_BOOLEAN__FLAGS (GClosure *closure,
@@ -163,6 +296,13 @@ extern void g_cclosure_marshal_BOOLEAN__FLAGS (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_BOOLEAN__FLAGSv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
#define g_cclosure_marshal_BOOL__FLAGS g_cclosure_marshal_BOOLEAN__FLAGS
/* STRING:OBJECT,POINTER (./gmarshal.list:28) */
@@ -172,6 +312,13 @@ extern void g_cclosure_marshal_STRING__OBJECT_POINTER (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_STRING__OBJECT_POINTERv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
/* BOOL:BOXED,BOXED (./gmarshal.list:29) */
extern void g_cclosure_marshal_BOOLEAN__BOXED_BOXED (GClosure *closure,
@@ -180,6 +327,13 @@ extern void g_cclosure_marshal_BOOLEAN__BOXED_BOXED (GClosure *closure,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data);
+extern void g_cclosure_marshal_BOOLEAN__BOXED_BOXEDv (GClosure *closure,
+ GValue *return_value,
+ gpointer instance,
+ va_list args,
+ gpointer marshal_data,
+ int n_params,
+ GType *param_types);
#define g_cclosure_marshal_BOOL__BOXED_BOXED g_cclosure_marshal_BOOLEAN__BOXED_BOXED
G_END_DECLS
diff --git a/gobject/gsignal.c b/gobject/gsignal.c
index 573673284..09c619539 100644
--- a/gobject/gsignal.c
+++ b/gobject/gsignal.c
@@ -106,7 +106,9 @@
#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org"
#ifdef G_ENABLE_DEBUG
-#define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond)
+#define COND_DEBUG(debug_type, cond) ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || (cond))
+#define IF_DEBUG(debug_type, cond) if (COND_DEBUG(debug_type, cond))
+
static volatile gpointer g_trace_instance_signals = NULL;
static volatile gpointer g_trap_instance_signals = NULL;
#endif /* G_ENABLE_DEBUG */
@@ -181,6 +183,7 @@ static gboolean signal_emit_unlocked_R (SignalNode *node,
const GValue *instance_and_params);
static const gchar * type_debug_name (GType type);
static void node_check_deprecated (const SignalNode *node);
+static void node_update_single_va_closure (SignalNode *node);
/* --- structures --- */
@@ -205,18 +208,22 @@ struct _SignalNode
guint destroyed : 1;
/* reinitializable portion */
- guint test_class_offset : 12;
guint flags : 9;
guint n_params : 8;
+ guint single_va_closure_is_valid : 1;
+ guint single_va_closure_is_after : 1;
GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
GBSearchArray *class_closure_bsa;
SignalAccumulator *accumulator;
GSignalCMarshaller c_marshaller;
+ GSignalCVaMarshaller va_marshaller;
GHookList *emission_hooks;
+
+ GClosure *single_va_closure;
};
-#define MAX_TEST_CLASS_OFFSET (4096) /* 2^12, 12 bits for test_class_offset */
-#define TEST_CLASS_MAGIC (1) /* indicates NULL class closure, candidate for NOP optimization */
+
+#define SINGLE_VA_CLOSURE_EMPTY_MAGIC GINT_TO_POINTER(1) /* indicates single_va_closure is valid but empty */
struct _SignalKey
{
@@ -502,7 +509,7 @@ handlers_find (gpointer instance,
((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
- handler->closure->meta_marshal == 0 &&
+ G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
((GCClosure*) handler->closure)->callback == func)))
{
mlist = handler_match_prepend (mlist, handler, signal_id);
@@ -539,7 +546,7 @@ handlers_find (gpointer instance,
((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
- handler->closure->meta_marshal == 0 &&
+ G_REAL_CLOSURE (handler->closure)->meta_marshal == NULL &&
((GCClosure*) handler->closure)->callback == func)))
{
mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
@@ -686,6 +693,47 @@ handler_insert (guint signal_id,
hlist->tail_after = handler;
}
+static void
+node_update_single_va_closure (SignalNode *node)
+{
+ GClosure *closure = NULL;
+ gboolean is_after = FALSE;
+
+ /* Fast path single-handler without boxing the arguments in GValues */
+ if (G_TYPE_IS_OBJECT (node->itype) &&
+ (node->flags & (G_SIGNAL_MUST_COLLECT)) == 0 &&
+ (node->emission_hooks == NULL || node->emission_hooks->hooks == NULL))
+ {
+ GSignalFlags run_type;
+ ClassClosure * cc;
+ GBSearchArray *bsa = node->class_closure_bsa;
+
+ if (bsa == NULL || bsa->n_nodes == 0)
+ closure = SINGLE_VA_CLOSURE_EMPTY_MAGIC;
+ else if (bsa->n_nodes == 1)
+ {
+ /* Look for default class closure (can't support non-default as it
+ chains up using GValues */
+ cc = g_bsearch_array_get_nth (bsa, &g_class_closure_bconfig, 0);
+ if (cc->instance_type == 0)
+ {
+ run_type = node->flags & (G_SIGNAL_RUN_FIRST|G_SIGNAL_RUN_LAST|G_SIGNAL_RUN_CLEANUP);
+ /* Only support *one* of run-first or run-last, not multiple or cleanup */
+ if (run_type == G_SIGNAL_RUN_FIRST ||
+ run_type == G_SIGNAL_RUN_LAST)
+ {
+ closure = cc->closure;
+ is_after = (run_type == G_SIGNAL_RUN_LAST);
+ }
+ }
+ }
+ }
+
+ node->single_va_closure_is_valid = TRUE;
+ node->single_va_closure = closure;
+ node->single_va_closure_is_after = is_after;
+}
+
static inline void
emission_push (Emission **emission_list_p,
Emission *emission)
@@ -942,6 +990,7 @@ g_signal_add_emission_hook (guint signal_id,
node->emission_hooks->seq_id = seq_hook_id;
g_hook_append (node->emission_hooks, hook);
seq_hook_id = node->emission_hooks->seq_id;
+
SIGNAL_UNLOCK ();
return hook->hook_id;
@@ -970,6 +1019,9 @@ g_signal_remove_emission_hook (guint signal_id,
g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id))
g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id);
+
+ node->single_va_closure_is_valid = FALSE;
+
SIGNAL_UNLOCK ();
}
@@ -1345,19 +1397,6 @@ g_signal_new (const gchar *signal_name,
va_end (args);
- /* optimize NOP emissions with NULL class handlers */
- if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE &&
- class_offset && class_offset < MAX_TEST_CLASS_OFFSET &&
- ~signal_flags & G_SIGNAL_MUST_COLLECT)
- {
- SignalNode *node;
-
- SIGNAL_LOCK ();
- node = LOOKUP_SIGNAL_NODE (signal_id);
- node->test_class_offset = class_offset;
- SIGNAL_UNLOCK ();
- }
-
return signal_id;
}
@@ -1480,8 +1519,7 @@ signal_add_class_closure (SignalNode *node,
{
ClassClosure key;
- /* can't optimize NOP emissions with overridden class closures */
- node->test_class_offset = 0;
+ node->single_va_closure_is_valid = FALSE;
if (!node->class_closure_bsa)
node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
@@ -1492,7 +1530,11 @@ signal_add_class_closure (SignalNode *node,
&key);
g_closure_sink (closure);
if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure))
- g_closure_set_marshal (closure, node->c_marshaller);
+ {
+ g_closure_set_marshal (closure, node->c_marshaller);
+ if (node->va_marshaller)
+ _g_closure_set_va_marshal (closure, node->va_marshaller);
+ }
}
/**
@@ -1540,6 +1582,8 @@ g_signal_newv (const gchar *signal_name,
gchar *name;
guint signal_id, i;
SignalNode *node;
+ GSignalCMarshaller builtin_c_marshaller;
+ GSignalCVaMarshaller va_marshaller;
g_return_val_if_fail (signal_name != NULL, 0);
g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0);
@@ -1629,9 +1673,9 @@ g_signal_newv (const gchar *signal_name,
TRACE(GOBJECT_SIGNAL_NEW(signal_id, name, itype));
}
node->destroyed = FALSE;
- node->test_class_offset = 0;
/* setup reinitializable portion */
+ node->single_va_closure_is_valid = FALSE;
node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
node->n_params = n_params;
node->param_types = g_memdup (param_types, sizeof (GType) * n_params);
@@ -1645,19 +1689,63 @@ g_signal_newv (const gchar *signal_name,
}
else
node->accumulator = NULL;
+
+ builtin_c_marshaller = NULL;
+ va_marshaller = NULL;
+
+ /* Pick up built-in va marshallers for standard types, and
+ instead of generic marshaller if no marshaller specified */
+ if (n_params == 0 && return_type == G_TYPE_NONE)
+ {
+ builtin_c_marshaller = g_cclosure_marshal_VOID__VOID;
+ va_marshaller = g_cclosure_marshal_VOID__VOIDv;
+ }
+ else if (n_params == 1 && return_type == G_TYPE_NONE)
+ {
+#define ADD_CHECK(__type__) \
+ else if (g_type_is_a (param_types[0] & ~G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_ ##__type__)) \
+ { \
+ builtin_c_marshaller = g_cclosure_marshal_VOID__ ## __type__; \
+ va_marshaller = g_cclosure_marshal_VOID__ ## __type__ ##v; \
+ }
+
+ if (0) {}
+ ADD_CHECK (BOOLEAN)
+ ADD_CHECK (CHAR)
+ ADD_CHECK (UCHAR)
+ ADD_CHECK (INT)
+ ADD_CHECK (UINT)
+ ADD_CHECK (LONG)
+ ADD_CHECK (ULONG)
+ ADD_CHECK (ENUM)
+ ADD_CHECK (FLAGS)
+ ADD_CHECK (FLOAT)
+ ADD_CHECK (DOUBLE)
+ ADD_CHECK (STRING)
+ ADD_CHECK (PARAM)
+ ADD_CHECK (BOXED)
+ ADD_CHECK (POINTER)
+ ADD_CHECK (OBJECT)
+ ADD_CHECK (VARIANT)
+ }
+
if (c_marshaller == NULL)
- c_marshaller = g_cclosure_marshal_generic;
+ {
+ if (builtin_c_marshaller)
+ c_marshaller = builtin_c_marshaller;
+ else
+ {
+ c_marshaller = g_cclosure_marshal_generic;
+ va_marshaller = g_cclosure_marshal_generic_va;
+ }
+ }
+
node->c_marshaller = c_marshaller;
+ node->va_marshaller = va_marshaller;
node->emission_hooks = NULL;
if (class_closure)
signal_add_class_closure (node, 0, class_closure);
- else if (G_TYPE_IS_INSTANTIATABLE (itype) &&
- return_type == G_TYPE_NONE &&
- ~signal_flags & G_SIGNAL_MUST_COLLECT)
- {
- /* optimize NOP emissions */
- node->test_class_offset = TEST_CLASS_MAGIC;
- }
+
SIGNAL_UNLOCK ();
g_free (name);
@@ -1665,6 +1753,35 @@ g_signal_newv (const gchar *signal_name,
return signal_id;
}
+void
+g_signal_set_va_marshaller (guint signal_id,
+ GType instance_type,
+ GSignalCVaMarshaller va_marshaller)
+{
+ SignalNode *node;
+
+ g_return_if_fail (signal_id > 0);
+ g_return_if_fail (va_marshaller != NULL);
+
+ SIGNAL_LOCK ();
+ node = LOOKUP_SIGNAL_NODE (signal_id);
+ if (node)
+ {
+ node->va_marshaller = va_marshaller;
+ if (node->class_closure_bsa)
+ {
+ ClassClosure *cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0);
+ if (cc->closure->marshal == node->c_marshaller)
+ _g_closure_set_va_marshal (cc->closure, va_marshaller);
+ }
+ }
+
+ node->single_va_closure_is_valid = FALSE;
+
+ SIGNAL_UNLOCK ();
+}
+
+
/**
* g_signal_new_valist:
* @signal_name: the name for the signal
@@ -1734,13 +1851,14 @@ signal_destroy_R (SignalNode *signal_node)
signal_node->destroyed = TRUE;
/* reentrancy caution, zero out real contents first */
- signal_node->test_class_offset = 0;
+ signal_node->single_va_closure_is_valid = FALSE;
signal_node->n_params = 0;
signal_node->param_types = NULL;
signal_node->return_type = 0;
signal_node->class_closure_bsa = NULL;
signal_node->accumulator = NULL;
signal_node->c_marshaller = NULL;
+ signal_node->va_marshaller = NULL;
signal_node->emission_hooks = NULL;
#ifdef G_ENABLE_DEBUG
@@ -2166,7 +2284,11 @@ g_signal_connect_closure_by_id (gpointer instance,
g_closure_sink (closure);
handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure))
- g_closure_set_marshal (closure, node->c_marshaller);
+ {
+ g_closure_set_marshal (closure, node->c_marshaller);
+ if (node->va_marshaller)
+ _g_closure_set_va_marshal (closure, node->va_marshaller);
+ }
}
}
else
@@ -2224,7 +2346,11 @@ g_signal_connect_closure (gpointer instance,
g_closure_sink (closure);
handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
- g_closure_set_marshal (handler->closure, node->c_marshaller);
+ {
+ g_closure_set_marshal (handler->closure, node->c_marshaller);
+ if (node->va_marshaller)
+ _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
+ }
}
}
else
@@ -2318,8 +2444,12 @@ g_signal_connect_data (gpointer instance,
g_closure_sink (handler->closure);
handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure))
- g_closure_set_marshal (handler->closure, node->c_marshaller);
- }
+ {
+ g_closure_set_marshal (handler->closure, node->c_marshaller);
+ if (node->va_marshaller)
+ _g_closure_set_va_marshal (handler->closure, node->va_marshaller);
+ }
+ }
}
else
g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
@@ -2791,50 +2921,6 @@ g_signal_has_handler_pending (gpointer instance,
return has_pending;
}
-static inline gboolean
-signal_check_skip_emission (SignalNode *node,
- gpointer instance,
- GQuark detail)
-{
- HandlerList *hlist;
-
- /* are we able to check for NULL class handlers? */
- if (!node->test_class_offset)
- return FALSE;
-
- /* are there emission hooks pending? */
- if (node->emission_hooks && node->emission_hooks->hooks)
- return FALSE;
-
- /* is there a non-NULL class handler? */
- if (node->test_class_offset != TEST_CLASS_MAGIC)
- {
- GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass);
-
- if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset))
- return FALSE;
- }
-
- /* are signals being debugged? */
-#ifdef G_ENABLE_DEBUG
- IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals)
- return FALSE;
-#endif /* G_ENABLE_DEBUG */
-
- /* is this a no-recurse signal already in emission? */
- if (node->flags & G_SIGNAL_NO_RECURSE &&
- emission_find (g_restart_emissions, node->signal_id, detail, instance))
- return FALSE;
-
- /* do we have pending handlers? */
- hlist = handler_list_lookup (node->signal_id, instance);
- if (hlist && hlist->handlers)
- return FALSE;
-
- /* none of the above, no emission required */
- return TRUE;
-}
-
/**
* g_signal_emitv:
* @instance_and_params: (array): argument list for the signal emission.
@@ -2925,18 +3011,49 @@ g_signal_emitv (const GValue *instance_and_params,
#endif /* G_ENABLE_DEBUG */
/* optimize NOP emissions */
- if (signal_check_skip_emission (node, instance, detail))
+ if (!node->single_va_closure_is_valid)
+ node_update_single_va_closure (node);
+
+ if (node->single_va_closure != NULL &&
+ (node->single_va_closure == SINGLE_VA_CLOSURE_EMPTY_MAGIC ||
+ _g_closure_is_void (node->single_va_closure, instance))
+#ifdef G_ENABLE_DEBUG
+ && !COND_DEBUG (SIGNALS, g_trace_instance_signals != instance &&
+ g_trap_instance_signals == instance)
+#endif /* G_ENABLE_DEBUG */
+ )
{
- /* nothing to do to emit this signal */
- SIGNAL_UNLOCK ();
- /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
- return;
+ HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
+ if (hlist == NULL || hlist->handlers == NULL)
+ {
+ /* nothing to do to emit this signal */
+ SIGNAL_UNLOCK ();
+ /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
+ return;
+ }
}
SIGNAL_UNLOCK ();
signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params);
}
+static inline gboolean
+accumulate (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ GValue *handler_return,
+ SignalAccumulator *accumulator)
+{
+ gboolean continue_emission;
+
+ if (!accumulator)
+ return TRUE;
+
+ continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
+ g_value_reset (handler_return);
+
+ return continue_emission;
+}
+
/**
* g_signal_emit_valist:
* @instance: the instance the signal is being emitted on.
@@ -2983,13 +3100,158 @@ g_signal_emit_valist (gpointer instance,
}
#endif /* !G_DISABLE_CHECKS */
- /* optimize NOP emissions */
- if (signal_check_skip_emission (node, instance, detail))
+ if (!node->single_va_closure_is_valid)
+ node_update_single_va_closure (node);
+
+ if (node->single_va_closure != NULL
+#ifdef G_ENABLE_DEBUG
+ && !COND_DEBUG (SIGNALS, g_trace_instance_signals != instance &&
+ g_trap_instance_signals == instance)
+#endif /* G_ENABLE_DEBUG */
+ )
{
- /* nothing to do to emit this signal */
- SIGNAL_UNLOCK ();
- /* g_printerr ("omitting emission of \"%s\"\n", node->name); */
- return;
+ HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
+ Handler *l;
+ GClosure *closure = NULL;
+ gboolean fastpath = TRUE;
+ GSignalFlags run_type = G_SIGNAL_RUN_FIRST;
+
+ if (node->single_va_closure != SINGLE_VA_CLOSURE_EMPTY_MAGIC &&
+ !_g_closure_is_void (node->single_va_closure, instance))
+ {
+ if (_g_closure_supports_invoke_va (node->single_va_closure))
+ {
+ closure = node->single_va_closure;
+ if (node->single_va_closure_is_after)
+ run_type = G_SIGNAL_RUN_LAST;
+ else
+ run_type = G_SIGNAL_RUN_FIRST;
+ }
+ else
+ fastpath = FALSE;
+ }
+
+ for (l = hlist ? hlist->handlers : NULL; fastpath && l != NULL; l = l->next)
+ {
+ if (!l->block_count &&
+ (!l->detail || l->detail == detail))
+ {
+ if (closure != NULL || !_g_closure_supports_invoke_va (l->closure))
+ {
+ fastpath = FALSE;
+ break;
+ }
+ else
+ {
+ closure = l->closure;
+ if (l->after)
+ run_type = G_SIGNAL_RUN_LAST;
+ else
+ run_type = G_SIGNAL_RUN_FIRST;
+ }
+ }
+ }
+
+ if (fastpath && closure == NULL && node->return_type == G_TYPE_NONE)
+ {
+ SIGNAL_UNLOCK ();
+ return;
+ }
+
+ /* Don't allow no-recurse emission as we might have to restart, which means
+ we will run multiple handlers and thus must ref all arguments */
+ if (closure != NULL && node->flags & (G_SIGNAL_NO_RECURSE) != 0)
+ fastpath = FALSE;
+
+ if (fastpath)
+ {
+ SignalAccumulator *accumulator;
+ Emission emission;
+ GValue *return_accu, accu = G_VALUE_INIT;
+ guint signal_id;
+ GValue emission_return = G_VALUE_INIT;
+ GType rtype = node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
+ gboolean static_scope = node->return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
+
+ signal_id = node->signal_id;
+ accumulator = node->accumulator;
+ if (rtype == G_TYPE_NONE)
+ return_accu = NULL;
+ else if (accumulator)
+ return_accu = &accu;
+ else
+ return_accu = &emission_return;
+
+ emission.instance = instance;
+ emission.ihint.signal_id = node->signal_id;
+ emission.ihint.detail = detail;
+ emission.ihint.run_type = run_type;
+ emission.state = EMISSION_RUN;
+ emission.chain_type = G_TYPE_FROM_INSTANCE (instance);
+ emission_push (&g_recursive_emissions, &emission);
+
+ SIGNAL_UNLOCK ();
+
+ TRACE(GOBJECT_SIGNAL_EMIT(signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
+
+ if (rtype != G_TYPE_NONE)
+ g_value_init (&emission_return, rtype);
+
+ if (accumulator)
+ g_value_init (&accu, rtype);
+
+ if (closure != NULL)
+ {
+ g_object_ref (instance);
+ _g_closure_invoke_va (closure,
+ return_accu,
+ instance,
+ var_args,
+ node->n_params,
+ node->param_types);
+ accumulate (&emission.ihint, &emission_return, &accu, accumulator);
+ g_object_unref (instance);
+ }
+
+ SIGNAL_LOCK ();
+
+ emission.chain_type = G_TYPE_NONE;
+ emission_pop (&g_recursive_emissions, &emission);
+
+ SIGNAL_UNLOCK ();
+
+ if (accumulator)
+ g_value_unset (&accu);
+
+ if (rtype != G_TYPE_NONE)
+ {
+ gchar *error = NULL;
+ for (i = 0; i < node->n_params; i++)
+ {
+ GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
+ G_VALUE_COLLECT_SKIP (ptype, var_args);
+ }
+
+ G_VALUE_LCOPY (&emission_return,
+ var_args,
+ static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
+ &error);
+ if (!error)
+ g_value_unset (&emission_return);
+ else
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occurred
+ */
+ }
+ }
+
+ TRACE(GOBJECT_SIGNAL_EMIT_END(signal_id, detail, instance, G_TYPE_FROM_INSTANCE (instance)));
+
+ return;
+ }
}
n_params = node->n_params;
@@ -3131,23 +3393,6 @@ g_signal_emit_by_name (gpointer instance,
g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance);
}
-static inline gboolean
-accumulate (GSignalInvocationHint *ihint,
- GValue *return_accu,
- GValue *handler_return,
- SignalAccumulator *accumulator)
-{
- gboolean continue_emission;
-
- if (!accumulator)
- return TRUE;
-
- continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data);
- g_value_reset (handler_return);
-
- return continue_emission;
-}
-
static gboolean
signal_emit_unlocked_R (SignalNode *node,
GQuark detail,
diff --git a/gobject/gsignal.h b/gobject/gsignal.h
index 73dcf47a1..966b6c740 100644
--- a/gobject/gsignal.h
+++ b/gobject/gsignal.h
@@ -44,6 +44,14 @@ typedef struct _GSignalInvocationHint GSignalInvocationHint;
*/
typedef GClosureMarshal GSignalCMarshaller;
/**
+ * GSignalCVaMarshaller:
+ *
+ * This is the signature of va_list marshaller functions, an optional
+ * marshaller that can be used in some situations to avoid
+ * marshalling the signal argument into GValues.
+ */
+typedef GVaClosureMarshal GSignalCVaMarshaller;
+/**
* GSignalEmissionHook:
* @ihint: Signal invocation hint, see #GSignalInvocationHint.
* @n_param_values: the number of parameters to the function, including
@@ -294,6 +302,9 @@ guint g_signal_new_class_handler (const gchar *signal_name,
GType return_type,
guint n_params,
...);
+void g_signal_set_va_marshaller (guint signal_id,
+ GType instance_type,
+ GSignalCVaMarshaller va_marshaller);
void g_signal_emitv (const GValue *instance_and_params,
guint signal_id,
diff --git a/gobject/gtype-private.h b/gobject/gtype-private.h
index 85b6c58ad..04a252b9f 100644
--- a/gobject/gtype-private.h
+++ b/gobject/gtype-private.h
@@ -24,9 +24,23 @@
#define __G_TYPE_PRIVATE_H__
#include "gboxed.h"
+#include "gclosure.h"
G_BEGIN_DECLS
+typedef struct _GRealClosure GRealClosure;
+struct _GRealClosure
+{
+ GClosureMarshal meta_marshal;
+ gpointer meta_marshal_data;
+ GVaClosureMarshal va_meta_marshal;
+ GVaClosureMarshal va_marshal;
+ GClosure closure;
+};
+
+#define G_REAL_CLOSURE(_c) \
+ ((GRealClosure *)G_STRUCT_MEMBER_P ((_c), -G_STRUCT_OFFSET (GRealClosure, closure)))
+
void _g_value_c_init (void); /* sync with gvalue.c */
void _g_value_types_init (void); /* sync with gvaluetypes.c */
void _g_enum_types_init (void); /* sync with genums.c */
@@ -46,6 +60,19 @@ void _g_type_boxed_init (GType type,
GBoxedCopyFunc copy_func,
GBoxedFreeFunc free_func);
+gboolean _g_closure_is_void (GClosure *closure,
+ gpointer instance);
+gboolean _g_closure_supports_invoke_va (GClosure *closure);
+void _g_closure_set_va_marshal (GClosure *closure,
+ GVaClosureMarshal marshal);
+void _g_closure_invoke_va (GClosure *closure,
+ GValue /*out*/ *return_value,
+ gpointer instance,
+ va_list args,
+ int n_params,
+ GType *param_types);
+
+
G_END_DECLS
#endif /* __G_TYPE_PRIVATE_H__ */
diff --git a/gobject/gvaluecollector.h b/gobject/gvaluecollector.h
index 9bdf48224..6d5190e07 100644
--- a/gobject/gvaluecollector.h
+++ b/gobject/gvaluecollector.h
@@ -158,6 +158,36 @@ G_STMT_START { \
G_VALUE_COLLECT_INIT(value, _value_type, var_args, flags, __error); \
} G_STMT_END
+#define G_VALUE_COLLECT_SKIP(_value_type, var_args) \
+G_STMT_START { \
+ GTypeValueTable *_vtable = g_type_value_table_peek (_value_type); \
+ gchar *_collect_format = _vtable->collect_format; \
+ \
+ while (*_collect_format) \
+ { \
+ switch (*_collect_format++) \
+ { \
+ case G_VALUE_COLLECT_INT: \
+ va_arg ((var_args), gint); \
+ break; \
+ case G_VALUE_COLLECT_LONG: \
+ va_arg ((var_args), glong); \
+ break; \
+ case G_VALUE_COLLECT_INT64: \
+ va_arg ((var_args), gint64); \
+ break; \
+ case G_VALUE_COLLECT_DOUBLE: \
+ va_arg ((var_args), gdouble); \
+ break; \
+ case G_VALUE_COLLECT_POINTER: \
+ va_arg ((var_args), gpointer); \
+ break; \
+ default: \
+ g_assert_not_reached (); \
+ } \
+ } \
+} G_STMT_END
+
/**
* G_VALUE_LCOPY:
* @value: a #GValue return location. @value is supposed to be initialized
diff --git a/gobject/tests/.gitignore b/gobject/tests/.gitignore
index 51a844d0f..20751f6ea 100644
--- a/gobject/tests/.gitignore
+++ b/gobject/tests/.gitignore
@@ -9,3 +9,4 @@ reference
signals
threadtests
valuearray
+marshalers.[ch]
diff --git a/gobject/tests/Makefile.am b/gobject/tests/Makefile.am
index fd3914a29..dec840dbf 100644
--- a/gobject/tests/Makefile.am
+++ b/gobject/tests/Makefile.am
@@ -18,4 +18,17 @@ TEST_PROGS += \
ifaceproperties \
valuearray
+signals_SOURCES = signals.c marshalers.c
+
+marshalers.h: Makefile.am marshalers.list
+ $(AM_V_GEN) ../glib-genmarshal --prefix=test $(srcdir)/marshalers.list --header --valist-marshallers > marshalers.h
+
+marshalers.c: Makefile.am marshalers.list
+ $(AM_V_GEN) ../glib-genmarshal --prefix=test $(srcdir)/marshalers.list --body --valist-marshallers > marshalers.c
+
+BUILT_SOURCES = marshalers.h marshalers.c
+CLEANFILES = marshalers.h marshalers.c
+
ifaceproperties_SOURCES = ifaceproperties.c testcommon.h
+
+EXTRA_DIST += marshalers.list
diff --git a/gobject/tests/marshalers.list b/gobject/tests/marshalers.list
new file mode 100644
index 000000000..19167ead5
--- /dev/null
+++ b/gobject/tests/marshalers.list
@@ -0,0 +1,3 @@
+VOID:INT,BOOLEAN,CHAR,UCHAR,UINT,LONG,ULONG,ENUM,FLAGS,FLOAT,DOUBLE,STRING,PARAM,BOXED,POINTER,OBJECT,VARIANT,INT64,UINT64
+INT:VOID
+UINT:VOID
diff --git a/gobject/tests/signals.c b/gobject/tests/signals.c
index e54fbffec..ee09a9ede 100644
--- a/gobject/tests/signals.c
+++ b/gobject/tests/signals.c
@@ -1,4 +1,5 @@
#include <glib-object.h>
+#include "marshalers.h"
typedef enum {
TEST_ENUM_NEGATIVE = -30,
@@ -55,6 +56,22 @@ test_unsigned_enum_get_type (void)
}
+static const GEnumValue my_enum_values[] =
+{
+ { 1, "the first value", "one" },
+ { 0, NULL, NULL }
+};
+
+static const GFlagsValue my_flag_values[] =
+{
+ { 1, "the first value", "one" },
+ { 0, NULL, NULL }
+};
+
+static GType enum_type;
+static GType flags_type;
+
+
typedef struct _Test Test;
typedef struct _TestClass TestClass;
@@ -63,11 +80,15 @@ struct _Test
GObject parent_instance;
};
+static void all_types_handler (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, gint e, guint f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test *obj, GVariant *var, gint64 i64, guint64 ui64);
+
struct _TestClass
{
GObjectClass parent_class;
void (* variant_changed) (Test *, GVariant *);
+ void (* all_types) (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, gint e, guint f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test *obj, GVariant *var, gint64 i64, guint64 ui64);
+ void (* all_types_null) (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, gint e, guint f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test *obj, GVariant *var, gint64 i64, guint64 ui64);
};
static GType test_get_type (void);
@@ -81,9 +102,16 @@ test_init (Test *test)
static void
test_class_init (TestClass *klass)
{
+ guint s;
+
+ enum_type = g_enum_register_static ("MyEnum", my_enum_values);
+ flags_type = g_flags_register_static ("MyFlag", my_flag_values);
+
+ klass->all_types = all_types_handler;
+
g_signal_new ("generic-marshaller-1",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+ G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
@@ -92,7 +120,7 @@ test_class_init (TestClass *klass)
G_TYPE_CHAR, G_TYPE_UCHAR, G_TYPE_INT, G_TYPE_LONG, G_TYPE_POINTER, G_TYPE_DOUBLE, G_TYPE_FLOAT);
g_signal_new ("generic-marshaller-2",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+ G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
@@ -101,7 +129,7 @@ test_class_init (TestClass *klass)
G_TYPE_INT, test_enum_get_type(), G_TYPE_INT, test_unsigned_enum_get_type (), G_TYPE_INT);
g_signal_new ("generic-marshaller-enum-return-signed",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+ G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
@@ -109,7 +137,7 @@ test_class_init (TestClass *klass)
0);
g_signal_new ("generic-marshaller-enum-return-unsigned",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+ G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
@@ -117,20 +145,40 @@ test_class_init (TestClass *klass)
0);
g_signal_new ("generic-marshaller-int-return",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+ G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_INT,
0);
+ s = g_signal_new ("va-marshaller-int-return",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ test_INT__VOID,
+ G_TYPE_INT,
+ 0);
+ g_signal_set_va_marshaller (s, G_TYPE_FROM_CLASS (klass),
+ test_INT__VOIDv);
g_signal_new ("generic-marshaller-uint-return",
G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
+ G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
NULL,
G_TYPE_UINT,
0);
+ s = g_signal_new ("va-marshaller-uint-return",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ test_INT__VOID,
+ G_TYPE_UINT,
+ 0);
+ g_signal_set_va_marshaller (s, G_TYPE_FROM_CLASS (klass),
+ test_UINT__VOIDv);
g_signal_new ("variant-changed-no-slot",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
@@ -149,6 +197,144 @@ test_class_init (TestClass *klass)
G_TYPE_NONE,
1,
G_TYPE_VARIANT);
+ g_signal_new ("all-types",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TestClass, all_types),
+ NULL, NULL,
+ test_VOID__INT_BOOLEAN_CHAR_UCHAR_UINT_LONG_ULONG_ENUM_FLAGS_FLOAT_DOUBLE_STRING_PARAM_BOXED_POINTER_OBJECT_VARIANT_INT64_UINT64,
+ G_TYPE_NONE,
+ 19,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ enum_type,
+ flags_type,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_PARAM_LONG,
+ G_TYPE_BYTES,
+ G_TYPE_POINTER,
+ test_get_type (),
+ G_TYPE_VARIANT,
+ G_TYPE_INT64,
+ G_TYPE_UINT64);
+ s = g_signal_new ("all-types-va",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TestClass, all_types),
+ NULL, NULL,
+ test_VOID__INT_BOOLEAN_CHAR_UCHAR_UINT_LONG_ULONG_ENUM_FLAGS_FLOAT_DOUBLE_STRING_PARAM_BOXED_POINTER_OBJECT_VARIANT_INT64_UINT64,
+ G_TYPE_NONE,
+ 19,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ enum_type,
+ flags_type,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_PARAM_LONG,
+ G_TYPE_BYTES,
+ G_TYPE_POINTER,
+ test_get_type (),
+ G_TYPE_VARIANT,
+ G_TYPE_INT64,
+ G_TYPE_UINT64);
+ g_signal_set_va_marshaller (s, G_TYPE_FROM_CLASS (klass),
+ test_VOID__INT_BOOLEAN_CHAR_UCHAR_UINT_LONG_ULONG_ENUM_FLAGS_FLOAT_DOUBLE_STRING_PARAM_BOXED_POINTER_OBJECT_VARIANT_INT64_UINT64v);
+
+ g_signal_new ("all-types-generic",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TestClass, all_types),
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE,
+ 19,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ enum_type,
+ flags_type,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_PARAM_LONG,
+ G_TYPE_BYTES,
+ G_TYPE_POINTER,
+ test_get_type (),
+ G_TYPE_VARIANT,
+ G_TYPE_INT64,
+ G_TYPE_UINT64);
+ g_signal_new ("all-types-null",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TestClass, all_types_null),
+ NULL, NULL,
+ test_VOID__INT_BOOLEAN_CHAR_UCHAR_UINT_LONG_ULONG_ENUM_FLAGS_FLOAT_DOUBLE_STRING_PARAM_BOXED_POINTER_OBJECT_VARIANT_INT64_UINT64,
+ G_TYPE_NONE,
+ 19,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ enum_type,
+ flags_type,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_PARAM_LONG,
+ G_TYPE_BYTES,
+ G_TYPE_POINTER,
+ test_get_type (),
+ G_TYPE_VARIANT,
+ G_TYPE_INT64,
+ G_TYPE_UINT64);
+ g_signal_new ("all-types-empty",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ test_VOID__INT_BOOLEAN_CHAR_UCHAR_UINT_LONG_ULONG_ENUM_FLAGS_FLOAT_DOUBLE_STRING_PARAM_BOXED_POINTER_OBJECT_VARIANT_INT64_UINT64,
+ G_TYPE_NONE,
+ 19,
+ G_TYPE_INT,
+ G_TYPE_BOOLEAN,
+ G_TYPE_CHAR,
+ G_TYPE_UCHAR,
+ G_TYPE_UINT,
+ G_TYPE_LONG,
+ G_TYPE_ULONG,
+ enum_type,
+ flags_type,
+ G_TYPE_FLOAT,
+ G_TYPE_DOUBLE,
+ G_TYPE_STRING,
+ G_TYPE_PARAM_LONG,
+ G_TYPE_BYTES,
+ G_TYPE_POINTER,
+ test_get_type (),
+ G_TYPE_VARIANT,
+ G_TYPE_INT64,
+ G_TYPE_UINT64);
}
static void
@@ -371,6 +557,27 @@ test_generic_marshaller_signal_int_return (void)
g_assert_cmpint (retval, ==, 2);
g_signal_handler_disconnect (test, id);
+ /* Same test for va marshaller */
+
+ /* Test return value -30 */
+ id = g_signal_connect (test,
+ "va-marshaller-int-return",
+ G_CALLBACK (on_generic_marshaller_int_return_signed_1),
+ NULL);
+ g_signal_emit_by_name (test, "va-marshaller-int-return", &retval);
+ g_assert_cmpint (retval, ==, -30);
+ g_signal_handler_disconnect (test, id);
+
+ /* Test return value positive */
+ retval = 0;
+ id = g_signal_connect (test,
+ "va-marshaller-int-return",
+ G_CALLBACK (on_generic_marshaller_int_return_signed_2),
+ NULL);
+ g_signal_emit_by_name (test, "va-marshaller-int-return", &retval);
+ g_assert_cmpint (retval, ==, 2);
+ g_signal_handler_disconnect (test, id);
+
g_object_unref (test);
}
@@ -412,7 +619,146 @@ test_generic_marshaller_signal_uint_return (void)
g_assert_cmpint (retval, ==, G_MAXUINT);
g_signal_handler_disconnect (test, id);
- g_object_unref (test);
+ /* Same test for va marshaller */
+
+ id = g_signal_connect (test,
+ "va-marshaller-uint-return",
+ G_CALLBACK (on_generic_marshaller_uint_return_1),
+ NULL);
+ g_signal_emit_by_name (test, "va-marshaller-uint-return", &retval);
+ g_assert_cmpint (retval, ==, 1);
+ g_signal_handler_disconnect (test, id);
+
+ retval = 0;
+ id = g_signal_connect (test,
+ "va-marshaller-uint-return",
+ G_CALLBACK (on_generic_marshaller_uint_return_2),
+ NULL);
+ g_signal_emit_by_name (test, "va-marshaller-uint-return", &retval);
+ g_assert_cmpint (retval, ==, G_MAXUINT);
+ g_signal_handler_disconnect (test, id);
+
+g_object_unref (test);
+}
+
+static int all_type_handlers_count = 0;
+
+static void
+all_types_handler (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, gint e, guint f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test *obj, GVariant *var, gint64 i64, guint64 ui64)
+{
+ all_type_handlers_count++;
+
+ g_assert_cmpint (i, ==, 42);
+ g_assert_cmpint (b, ==, TRUE);
+ g_assert_cmpint (c, ==, 17);
+ g_assert_cmpuint (uc, ==, 140);
+ g_assert_cmpuint (ui, ==, G_MAXUINT - 42);
+ g_assert_cmpint (l, ==, -1117);
+ g_assert_cmpuint (ul, ==, G_MAXULONG - 999);
+ g_assert_cmpint (e, ==, 1);
+ g_assert_cmpuint (f, ==, 0);
+ g_assert_cmpfloat (fl, ==, 0.25);
+ g_assert_cmpfloat (db, ==, 1.5);
+ g_assert_cmpstr (str, ==, "Test");
+ g_assert_cmpstr (g_param_spec_get_nick (param), ==, "nick");
+ g_assert_cmpstr (g_bytes_get_data (bytes, NULL), ==, "Blah");
+ g_assert (ptr == &enum_type);
+ g_assert_cmpuint (g_variant_get_uint16 (var), == , 99);
+ g_assert_cmpint (i64, ==, G_MAXINT64 - 1234);
+ g_assert_cmpuint (ui64, ==, G_MAXUINT64 - 123456);
+}
+
+static void
+all_types_handler_cb (Test *test, int i, gboolean b, char c, guchar uc, guint ui, glong l, gulong ul, gint e, guint f, float fl, double db, char *str, GParamSpec *param, GBytes *bytes, gpointer ptr, Test *obj, GVariant *var, gint64 i64, guint64 ui64, gpointer user_data)
+{
+ g_assert (user_data == &flags_type);
+ all_types_handler (test, i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, obj, var, i64, ui64);
+}
+
+static void
+test_all_types (void)
+{
+ Test *test;
+
+ int i = 42;
+ gboolean b = TRUE;
+ char c = 17;
+ guchar uc = 140;
+ guint ui = G_MAXUINT - 42;
+ glong l = -1117;
+ gulong ul = G_MAXULONG - 999;
+ gint e = 1;
+ guint f = 0;
+ float fl = 0.25;
+ double db = 1.5;
+ char *str = "Test";
+ GParamSpec *param = g_param_spec_long ("param", "nick", "blurb", 0, 10, 4, 0);
+ GBytes *bytes = g_bytes_new_static ("Blah", 5);
+ gpointer ptr = &enum_type;
+ GVariant *var = g_variant_new_uint16 (99);
+ g_variant_ref_sink (var);
+ gint64 i64 = G_MAXINT64 - 1234;
+ guint64 ui64 = G_MAXUINT64 - 123456;
+
+ test = g_object_new (test_get_type (), NULL);
+
+ all_type_handlers_count = 0;
+
+ g_signal_emit_by_name (test, "all-types",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-va",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-generic",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-empty",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-null",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+
+ g_assert_cmpint (all_type_handlers_count, ==, 3);
+
+ all_type_handlers_count = 0;
+
+ g_signal_connect (test, "all-types", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-va", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-generic", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-empty", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-null", G_CALLBACK (all_types_handler_cb), &flags_type);
+
+ g_signal_emit_by_name (test, "all-types",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-va",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-generic",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-empty",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-null",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+
+ g_assert_cmpint (all_type_handlers_count, ==, 3 + 5);
+
+ all_type_handlers_count = 0;
+
+ g_signal_connect (test, "all-types", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-va", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-generic", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-empty", G_CALLBACK (all_types_handler_cb), &flags_type);
+ g_signal_connect (test, "all-types-null", G_CALLBACK (all_types_handler_cb), &flags_type);
+
+ g_signal_emit_by_name (test, "all-types",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-va",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-generic",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-empty",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+ g_signal_emit_by_name (test, "all-types-null",
+ i, b, c, uc, ui, l, ul, e, f, fl, db, str, param, bytes, ptr, test, var, i64, ui64);
+
+ g_assert_cmpint (all_type_handlers_count, ==, 3 + 5 + 5);
+
}
/* --- */
@@ -425,6 +771,7 @@ main (int argc,
g_test_init (&argc, &argv, NULL);
+ g_test_add_func ("/gobject/signals/all-types", test_all_types);
g_test_add_func ("/gobject/signals/variant", test_variant_signal);
g_test_add_func ("/gobject/signals/generic-marshaller-1", test_generic_marshaller_signal_1);
g_test_add_func ("/gobject/signals/generic-marshaller-2", test_generic_marshaller_signal_2);