diff options
author | Alexander Larsson <alexl@redhat.com> | 2012-03-05 12:29:45 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2012-03-05 12:29:45 +0100 |
commit | f3fb42cfaf967cec4450437d81f824de266fb274 (patch) | |
tree | b6cf954c7982fe2dbe0c2d4d487003562b46bcf8 /gobject | |
parent | e9c399a65bfa1796947a8d1d65a4a7edab610c3b (diff) | |
parent | 2d6502f67bb207c5a0d6eaba27b2398b74baa28f (diff) | |
download | glib-f3fb42cfaf967cec4450437d81f824de266fb274.tar.gz |
Merge branch 'signal-performance'
Diffstat (limited to 'gobject')
-rw-r--r-- | gobject/gclosure.c | 481 | ||||
-rw-r--r-- | gobject/gclosure.h | 24 | ||||
-rw-r--r-- | gobject/glib-genmarshal.c | 232 | ||||
-rw-r--r-- | gobject/gmarshal.c | 909 | ||||
-rw-r--r-- | gobject/gmarshal.h | 154 | ||||
-rw-r--r-- | gobject/gsignal.c | 461 | ||||
-rw-r--r-- | gobject/gsignal.h | 11 | ||||
-rw-r--r-- | gobject/gtype-private.h | 27 | ||||
-rw-r--r-- | gobject/gvaluecollector.h | 30 | ||||
-rw-r--r-- | gobject/tests/.gitignore | 1 | ||||
-rw-r--r-- | gobject/tests/Makefile.am | 13 | ||||
-rw-r--r-- | gobject/tests/marshalers.list | 3 | ||||
-rw-r--r-- | gobject/tests/signals.c | 361 |
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); |