Merge branch 'signal-performance'

This commit is contained in:
Alexander Larsson 2012-03-05 12:29:45 +01:00
commit f3fb42cfaf
14 changed files with 2725 additions and 215 deletions

View File

@ -34,6 +34,7 @@
#include "genums.h" #include "genums.h"
#include "gvalue.h" #include "gvalue.h"
#include "gvaluetypes.h" #include "gvaluetypes.h"
#include "gtype-private.h"
/** /**
@ -90,13 +91,11 @@
* </itemizedlist> * </itemizedlist>
*/ */
#define CLOSURE_MAX_REF_COUNT ((1 << 15) - 1) #define CLOSURE_MAX_REF_COUNT ((1 << 15) - 1)
#define CLOSURE_MAX_N_GUARDS ((1 << 1) - 1) #define CLOSURE_MAX_N_GUARDS ((1 << 1) - 1)
#define CLOSURE_MAX_N_FNOTIFIERS ((1 << 2) - 1) #define CLOSURE_MAX_N_FNOTIFIERS ((1 << 2) - 1)
#define CLOSURE_MAX_N_INOTIFIERS ((1 << 8) - 1) #define CLOSURE_MAX_N_INOTIFIERS ((1 << 8) - 1)
#define CLOSURE_N_MFUNCS(cl) ((cl)->meta_marshal + \ #define CLOSURE_N_MFUNCS(cl) (((cl)->n_guards << 1L))
((cl)->n_guards << 1L))
/* same as G_CLOSURE_N_NOTIFIERS() (keep in sync) */ /* same as G_CLOSURE_N_NOTIFIERS() (keep in sync) */
#define CLOSURE_N_NOTIFIERS(cl) (CLOSURE_N_MFUNCS (cl) + \ #define CLOSURE_N_NOTIFIERS(cl) (CLOSURE_N_MFUNCS (cl) + \
(cl)->n_fnotifiers + \ (cl)->n_fnotifiers + \
@ -198,25 +197,17 @@ GClosure*
g_closure_new_simple (guint sizeof_closure, g_closure_new_simple (guint sizeof_closure,
gpointer data) gpointer data)
{ {
GRealClosure *real_closure;
GClosure *closure; GClosure *closure;
g_return_val_if_fail (sizeof_closure >= sizeof (GClosure), NULL); 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, 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, floating, TRUE);
SET (closure, derivative_flag, 0);
SET (closure, in_marshal, FALSE);
SET (closure, is_invalid, FALSE);
closure->marshal = NULL;
closure->data = data; closure->data = data;
closure->notifiers = NULL;
memset (G_STRUCT_MEMBER_P (closure, sizeof (*closure)), 0, sizeof_closure - sizeof (*closure));
return closure; return closure;
} }
@ -226,10 +217,10 @@ closure_invoke_notifiers (GClosure *closure,
guint notify_type) guint notify_type)
{ {
/* notifier layout: /* notifier layout:
* meta_marshal n_guards n_guards n_fnotif. n_inotifiers * n_guards n_guards n_fnotif. n_inotifiers
* ->[[meta_marshal][pre_guards][post_guards][fnotifiers][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 * CLOSURE_N_NOTIFIERS(cl) = CLOSURE_N_MFUNCS(cl) + n_fnotifiers + n_inotifiers
* *
* constrains/catches: * 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 prepare for callback removal during FNOTIFY and INOTIFY (done via ->marshal= & ->data=)
* - must distinguish (->marshal= & ->data=) for INOTIFY vs. FNOTIFY (via ->in_inotify) * - must distinguish (->marshal= & ->data=) for INOTIFY vs. FNOTIFY (via ->in_inotify)
* + closure->n_guards is const during PRE_NOTIFY & POST_NOTIFY * + 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 * + none of the callbacks can cause recursion
* + closure->n_inotifiers is const 0 during FNOTIFY * + closure->n_inotifiers is const 0 during FNOTIFY
*/ */
@ -279,7 +269,7 @@ closure_invoke_notifiers (GClosure *closure,
break; break;
case PRE_NOTIFY: case PRE_NOTIFY:
i = closure->n_guards; i = closure->n_guards;
offs = closure->meta_marshal; offs = 0;
while (i--) while (i--)
{ {
ndata = closure->notifiers + offs + i; ndata = closure->notifiers + offs + i;
@ -288,7 +278,7 @@ closure_invoke_notifiers (GClosure *closure,
break; break;
case POST_NOTIFY: case POST_NOTIFY:
i = closure->n_guards; i = closure->n_guards;
offs = closure->meta_marshal + i; offs = i;
while (i--) while (i--)
{ {
ndata = closure->notifiers + offs + 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) * g_closure_set_meta_marshal: (skip)
* @closure: a #GClosure * @closure: a #GClosure
@ -325,27 +333,19 @@ g_closure_set_meta_marshal (GClosure *closure,
gpointer marshal_data, gpointer marshal_data,
GClosureMarshal meta_marshal) GClosureMarshal meta_marshal)
{ {
GClosureNotifyData *notifiers; GRealClosure *real_closure;
g_return_if_fail (closure != NULL); g_return_if_fail (closure != NULL);
g_return_if_fail (meta_marshal != NULL); g_return_if_fail (meta_marshal != NULL);
g_return_if_fail (closure->is_invalid == FALSE); g_return_if_fail (closure->is_invalid == FALSE);
g_return_if_fail (closure->in_marshal == FALSE); g_return_if_fail (closure->in_marshal == FALSE);
g_return_if_fail (closure->meta_marshal == 0);
notifiers = closure->notifiers; real_closure = G_REAL_CLOSURE (closure);
closure->notifiers = g_renew (GClosureNotifyData, NULL, CLOSURE_N_NOTIFIERS (closure) + 1);
if (notifiers) g_return_if_fail (real_closure->meta_marshal == NULL);
{
/* usually the meta marshal will be setup right after creation, so the real_closure->meta_marshal = meta_marshal;
* g_memmove() should be rare-case scenario real_closure->meta_marshal_data = marshal_data;
*/
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);
} }
/** /**
@ -395,14 +395,13 @@ g_closure_add_marshal_guards (GClosure *closure,
closure->notifiers[(CLOSURE_N_MFUNCS (closure) + closure->notifiers[(CLOSURE_N_MFUNCS (closure) +
closure->n_fnotifiers)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 1]; closure->n_fnotifiers)] = closure->notifiers[CLOSURE_N_MFUNCS (closure) + 1];
if (closure->n_guards) if (closure->n_guards)
closure->notifiers[(closure->meta_marshal + closure->notifiers[(closure->n_guards +
closure->n_guards + closure->n_guards + 1)] = closure->notifiers[closure->n_guards];
closure->n_guards + 1)] = closure->notifiers[closure->meta_marshal + closure->n_guards];
i = closure->n_guards; i = closure->n_guards;
closure->notifiers[closure->meta_marshal + i].data = pre_marshal_data; closure->notifiers[i].data = pre_marshal_data;
closure->notifiers[closure->meta_marshal + i].notify = pre_marshal_notify; closure->notifiers[i].notify = pre_marshal_notify;
closure->notifiers[closure->meta_marshal + i + 1].data = post_marshal_data; closure->notifiers[i + 1].data = post_marshal_data;
closure->notifiers[closure->meta_marshal + i + 1].notify = post_marshal_notify; closure->notifiers[i + 1].notify = post_marshal_notify;
INC (closure, n_guards); INC (closure, n_guards);
} }
@ -599,7 +598,7 @@ g_closure_unref (GClosure *closure)
{ {
closure_invoke_notifiers (closure, FNOTIFY); closure_invoke_notifiers (closure, FNOTIFY);
g_free (closure->notifiers); 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, const GValue *param_values,
gpointer invocation_hint) gpointer invocation_hint)
{ {
GRealClosure *real_closure;
g_return_if_fail (closure != NULL); g_return_if_fail (closure != NULL);
real_closure = G_REAL_CLOSURE (closure);
g_closure_ref (closure); /* preserve floating flag */ g_closure_ref (closure); /* preserve floating flag */
if (!closure->is_invalid) if (!closure->is_invalid)
{ {
@ -756,13 +759,13 @@ g_closure_invoke (GClosure *closure,
gpointer marshal_data; gpointer marshal_data;
gboolean in_marshal = closure->in_marshal; 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); SET (closure, in_marshal, TRUE);
if (closure->meta_marshal) if (real_closure->meta_marshal)
{ {
marshal_data = closure->notifiers[0].data; marshal_data = real_closure->meta_marshal_data;
marshal = (GClosureMarshal) closure->notifiers[0].notify; marshal = real_closure->meta_marshal;
} }
else else
{ {
@ -783,6 +786,70 @@ g_closure_invoke (GClosure *closure,
g_closure_unref (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) * g_closure_set_marshal: (skip)
* @closure: a #GClosure * @closure: a #GClosure
@ -809,6 +876,24 @@ g_closure_set_marshal (GClosure *closure,
closure->marshal = marshal; 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) * g_cclosure_new: (skip)
* @callback_func: the function to invoke * @callback_func: the function to invoke
@ -889,6 +974,34 @@ g_type_class_meta_marshal (GClosure *closure,
callback); callback);
} }
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 static void
g_type_iface_meta_marshal (GClosure *closure, g_type_iface_meta_marshal (GClosure *closure,
GValue /*out*/ *return_value, GValue /*out*/ *return_value,
@ -912,6 +1025,70 @@ g_type_iface_meta_marshal (GClosure *closure,
callback); 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: * g_signal_type_cclosure_new:
* @itype: the #GType identifier of an interface or classed type * @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); closure = g_closure_new_simple (sizeof (GClosure), (gpointer) itype);
if (G_TYPE_IS_INTERFACE (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 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; 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: * g_cclosure_marshal_generic:
* @closure: A #GClosure. * @closure: A #GClosure.
@ -1192,6 +1454,123 @@ g_cclosure_marshal_generic (GClosure *closure,
value_from_ffi_type (return_gvalue, rvalue); 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: * g_cclosure_marshal_VOID__VOID:
* @closure: the #GClosure to which the marshaller belongs * @closure: the #GClosure to which the marshaller belongs

View File

@ -51,7 +51,7 @@ G_BEGIN_DECLS
* *
* Returns: number of notifiers * 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) (cl)->n_fnotifiers + (cl)->n_inotifiers)
/** /**
* G_CCLOSURE_SWAP_DATA: * G_CCLOSURE_SWAP_DATA:
@ -120,6 +120,15 @@ typedef void (*GClosureMarshal) (GClosure *closure,
const GValue *param_values, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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: * GCClosure:
* @closure: the #GClosure * @closure: the #GClosure
@ -149,7 +158,9 @@ struct _GClosure
{ {
/*< private >*/ /*< private >*/
volatile guint ref_count : 15; 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_guards : 1;
volatile guint n_fnotifiers : 2; /* finalization notifiers */ volatile guint n_fnotifiers : 2; /* finalization notifiers */
volatile guint n_inotifiers : 8; /* invalidation notifiers */ volatile guint n_inotifiers : 8; /* invalidation notifiers */
@ -256,6 +267,15 @@ void g_cclosure_marshal_generic (GClosure *closure,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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 G_END_DECLS
#endif /* __G_CLOSURE_H__ */ #endif /* __G_CLOSURE_H__ */

View File

@ -50,7 +50,12 @@ typedef struct
gchar *keyword; /* marhaller list keyword [MY_STRING] */ gchar *keyword; /* marhaller list keyword [MY_STRING] */
const gchar *sig_name; /* signature name [STRING] */ const gchar *sig_name; /* signature name [STRING] */
const gchar *ctype; /* C type name [gchar*] */ 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 *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; } InArgument;
typedef struct typedef struct
{ {
@ -122,6 +127,7 @@ static FILE *fout = NULL;
static gboolean gen_cheader = FALSE; static gboolean gen_cheader = FALSE;
static gboolean gen_cbody = FALSE; static gboolean gen_cbody = FALSE;
static gboolean gen_internal = FALSE; static gboolean gen_internal = FALSE;
static gboolean gen_valist = FALSE;
static gboolean skip_ploc = FALSE; static gboolean skip_ploc = FALSE;
static gboolean std_includes = TRUE; static gboolean std_includes = TRUE;
static gint exit_status = 0; static gint exit_status = 0;
@ -184,30 +190,30 @@ static gboolean
complete_in_arg (InArgument *iarg) complete_in_arg (InArgument *iarg)
{ {
static const InArgument args[] = { static const InArgument args[] = {
/* keyword sig_name ctype getter */ /* keyword sig_name ctype promoted getter */
{ "VOID", "VOID", "void", NULL, }, { "VOID", "VOID", "void", "void", NULL, },
{ "BOOLEAN", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", }, { "BOOLEAN", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
{ "CHAR", "CHAR", "gchar", "g_marshal_value_peek_char", }, { "CHAR", "CHAR", "gchar", "gint", "g_marshal_value_peek_char", },
{ "UCHAR", "UCHAR", "guchar", "g_marshal_value_peek_uchar", }, { "UCHAR", "UCHAR", "guchar", "guint", "g_marshal_value_peek_uchar", },
{ "INT", "INT", "gint", "g_marshal_value_peek_int", }, { "INT", "INT", "gint", "gint", "g_marshal_value_peek_int", },
{ "UINT", "UINT", "guint", "g_marshal_value_peek_uint", }, { "UINT", "UINT", "guint", "guint", "g_marshal_value_peek_uint", },
{ "LONG", "LONG", "glong", "g_marshal_value_peek_long", }, { "LONG", "LONG", "glong", "glong", "g_marshal_value_peek_long", },
{ "ULONG", "ULONG", "gulong", "g_marshal_value_peek_ulong", }, { "ULONG", "ULONG", "gulong", "gulong", "g_marshal_value_peek_ulong", },
{ "INT64", "INT64", "gint64", "g_marshal_value_peek_int64", }, { "INT64", "INT64", "gint64", "gint64", "g_marshal_value_peek_int64", },
{ "UINT64", "UINT64", "guint64", "g_marshal_value_peek_uint64", }, { "UINT64", "UINT64", "guint64", "guint64", "g_marshal_value_peek_uint64", },
{ "ENUM", "ENUM", "gint", "g_marshal_value_peek_enum", }, { "ENUM", "ENUM", "gint", "gint", "g_marshal_value_peek_enum", },
{ "FLAGS", "FLAGS", "guint", "g_marshal_value_peek_flags", }, { "FLAGS", "FLAGS", "guint", "guint", "g_marshal_value_peek_flags", },
{ "FLOAT", "FLOAT", "gfloat", "g_marshal_value_peek_float", }, { "FLOAT", "FLOAT", "gfloat", "gdouble", "g_marshal_value_peek_float", },
{ "DOUBLE", "DOUBLE", "gdouble", "g_marshal_value_peek_double", }, { "DOUBLE", "DOUBLE", "gdouble", "gdouble", "g_marshal_value_peek_double", },
{ "STRING", "STRING", "gpointer", "g_marshal_value_peek_string", }, { "STRING", "STRING", "gpointer", "gpointer", "g_marshal_value_peek_string", "g_strdup", "g_free"},
{ "PARAM", "PARAM", "gpointer", "g_marshal_value_peek_param", }, { "PARAM", "PARAM", "gpointer", "gpointer", "g_marshal_value_peek_param", "g_param_spec_ref", "g_param_spec_unref"},
{ "BOXED", "BOXED", "gpointer", "g_marshal_value_peek_boxed", }, { "BOXED", "BOXED", "gpointer", "gpointer", "g_marshal_value_peek_boxed", "g_boxed_copy", "g_boxed_free", FALSE, TRUE},
{ "POINTER", "POINTER", "gpointer", "g_marshal_value_peek_pointer", }, { "POINTER", "POINTER", "gpointer", "gpointer", "g_marshal_value_peek_pointer", },
{ "OBJECT", "OBJECT", "gpointer", "g_marshal_value_peek_object", }, { "OBJECT", "OBJECT", "gpointer", "gpointer", "g_marshal_value_peek_object", "g_object_ref", "g_object_unref", TRUE},
{ "VARIANT", "VARIANT", "gpointer", "g_marshal_value_peek_variant", }, { "VARIANT", "VARIANT", "gpointer", "gpointer", "g_marshal_value_peek_variant", "g_variant_ref_sink", "g_variant_unref"},
/* deprecated: */ /* deprecated: */
{ "NONE", "VOID", "void", NULL, }, { "NONE", "VOID", "void", "void", NULL, },
{ "BOOL", "BOOLEAN", "gboolean", "g_marshal_value_peek_boolean", }, { "BOOL", "BOOLEAN", "gboolean", "gboolean", "g_marshal_value_peek_boolean", },
}; };
guint i; guint i;
@ -218,7 +224,12 @@ complete_in_arg (InArgument *iarg)
{ {
iarg->sig_name = args[i].sig_name; iarg->sig_name = args[i].sig_name;
iarg->ctype = args[i].ctype; iarg->ctype = args[i].ctype;
iarg->promoted_ctype = args[i].promoted_ctype;
iarg->getter = args[i].getter; 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; return TRUE;
} }
@ -357,6 +368,7 @@ generate_marshal (const gchar *signame,
g_free (tmp); g_free (tmp);
} }
/* GValue marshaller */
if (gen_cheader && have_std_marshaller) if (gen_cheader && have_std_marshaller)
{ {
g_fprintf (fout, "#define %s_%s\t%s_%s\n", marshaller_prefix, signame, std_marshaller_prefix, signame); 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 */ /* cfile marshal footer */
g_fprintf (fout, "}\n"); 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 static void
@ -802,6 +982,11 @@ parse_args (gint *argc_p,
gen_internal = TRUE; gen_internal = TRUE;
argv[i] = NULL; argv[i] = NULL;
} }
else if (strcmp ("--valist-marshallers", argv[i]) == 0)
{
gen_valist = TRUE;
argv[i] = NULL;
}
else if ((strcmp ("--prefix", argv[i]) == 0) || else if ((strcmp ("--prefix", argv[i]) == 0) ||
(strncmp ("--prefix=", argv[i], 9) == 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, " --skip-source Skip source location comments\n");
g_fprintf (bout, " --stdinc, --nostdinc Include/use standard marshallers\n"); g_fprintf (bout, " --stdinc, --nostdinc Include/use standard marshallers\n");
g_fprintf (bout, " --internal Mark generated functions as internal\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, " -v, --version Print version informations\n");
g_fprintf (bout, " --g-fatal-warnings Make warnings fatal (abort)\n"); g_fprintf (bout, " --g-fatal-warnings Make warnings fatal (abort)\n");
} }

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,13 @@ extern void g_cclosure_marshal_VOID__VOID (GClosure *closure,
const GValue *param_values, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:BOOLEAN (./gmarshal.list:7) */
extern void g_cclosure_marshal_VOID__BOOLEAN (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:CHAR (./gmarshal.list:8) */
extern void g_cclosure_marshal_VOID__CHAR (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:UCHAR (./gmarshal.list:9) */
extern void g_cclosure_marshal_VOID__UCHAR (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:INT (./gmarshal.list:10) */
extern void g_cclosure_marshal_VOID__INT (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:UINT (./gmarshal.list:11) */
extern void g_cclosure_marshal_VOID__UINT (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:LONG (./gmarshal.list:12) */
extern void g_cclosure_marshal_VOID__LONG (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:ULONG (./gmarshal.list:13) */
extern void g_cclosure_marshal_VOID__ULONG (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:ENUM (./gmarshal.list:14) */
extern void g_cclosure_marshal_VOID__ENUM (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:FLAGS (./gmarshal.list:15) */
extern void g_cclosure_marshal_VOID__FLAGS (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:FLOAT (./gmarshal.list:16) */
extern void g_cclosure_marshal_VOID__FLOAT (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:DOUBLE (./gmarshal.list:17) */
extern void g_cclosure_marshal_VOID__DOUBLE (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:STRING (./gmarshal.list:18) */
extern void g_cclosure_marshal_VOID__STRING (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:PARAM (./gmarshal.list:19) */
extern void g_cclosure_marshal_VOID__PARAM (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:BOXED (./gmarshal.list:20) */
extern void g_cclosure_marshal_VOID__BOXED (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:POINTER (./gmarshal.list:21) */
extern void g_cclosure_marshal_VOID__POINTER (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:OBJECT (./gmarshal.list:22) */
extern void g_cclosure_marshal_VOID__OBJECT (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:VARIANT (./gmarshal.list:23) */
extern void g_cclosure_marshal_VOID__VARIANT (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* VOID:UINT,POINTER (./gmarshal.list:26) */
extern void g_cclosure_marshal_VOID__UINT_POINTER (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* BOOL:FLAGS (./gmarshal.list:27) */
extern void g_cclosure_marshal_BOOLEAN__FLAGS (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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 #define g_cclosure_marshal_BOOL__FLAGS g_cclosure_marshal_BOOLEAN__FLAGS
/* STRING:OBJECT,POINTER (./gmarshal.list:28) */ /* STRING:OBJECT,POINTER (./gmarshal.list:28) */
@ -172,6 +312,13 @@ extern void g_cclosure_marshal_STRING__OBJECT_POINTER (GClosure *closure,
const GValue *param_values, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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) */ /* BOOL:BOXED,BOXED (./gmarshal.list:29) */
extern void g_cclosure_marshal_BOOLEAN__BOXED_BOXED (GClosure *closure, 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, const GValue *param_values,
gpointer invocation_hint, gpointer invocation_hint,
gpointer marshal_data); 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 #define g_cclosure_marshal_BOOL__BOXED_BOXED g_cclosure_marshal_BOOLEAN__BOXED_BOXED
G_END_DECLS G_END_DECLS

View File

@ -106,7 +106,9 @@
#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org" #define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org"
#ifdef G_ENABLE_DEBUG #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_trace_instance_signals = NULL;
static volatile gpointer g_trap_instance_signals = NULL; static volatile gpointer g_trap_instance_signals = NULL;
#endif /* G_ENABLE_DEBUG */ #endif /* G_ENABLE_DEBUG */
@ -181,6 +183,7 @@ static gboolean signal_emit_unlocked_R (SignalNode *node,
const GValue *instance_and_params); const GValue *instance_and_params);
static const gchar * type_debug_name (GType type); static const gchar * type_debug_name (GType type);
static void node_check_deprecated (const SignalNode *node); static void node_check_deprecated (const SignalNode *node);
static void node_update_single_va_closure (SignalNode *node);
/* --- structures --- */ /* --- structures --- */
@ -205,18 +208,22 @@ struct _SignalNode
guint destroyed : 1; guint destroyed : 1;
/* reinitializable portion */ /* reinitializable portion */
guint test_class_offset : 12;
guint flags : 9; guint flags : 9;
guint n_params : 8; 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 *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */
GBSearchArray *class_closure_bsa; GBSearchArray *class_closure_bsa;
SignalAccumulator *accumulator; SignalAccumulator *accumulator;
GSignalCMarshaller c_marshaller; GSignalCMarshaller c_marshaller;
GSignalCVaMarshaller va_marshaller;
GHookList *emission_hooks; 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 struct _SignalKey
{ {
@ -502,7 +509,7 @@ handlers_find (gpointer instance,
((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && ((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))) ((GCClosure*) handler->closure)->callback == func)))
{ {
mlist = handler_match_prepend (mlist, handler, signal_id); 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_DATA) || handler->closure->data == data) &&
((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && ((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))) ((GCClosure*) handler->closure)->callback == func)))
{ {
mlist = handler_match_prepend (mlist, handler, hlist->signal_id); mlist = handler_match_prepend (mlist, handler, hlist->signal_id);
@ -686,6 +693,47 @@ handler_insert (guint signal_id,
hlist->tail_after = handler; 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 static inline void
emission_push (Emission **emission_list_p, emission_push (Emission **emission_list_p,
Emission *emission) Emission *emission)
@ -942,6 +990,7 @@ g_signal_add_emission_hook (guint signal_id,
node->emission_hooks->seq_id = seq_hook_id; node->emission_hooks->seq_id = seq_hook_id;
g_hook_append (node->emission_hooks, hook); g_hook_append (node->emission_hooks, hook);
seq_hook_id = node->emission_hooks->seq_id; seq_hook_id = node->emission_hooks->seq_id;
SIGNAL_UNLOCK (); SIGNAL_UNLOCK ();
return hook->hook_id; 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); g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id);
else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_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); 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 (); SIGNAL_UNLOCK ();
} }
@ -1345,19 +1397,6 @@ g_signal_new (const gchar *signal_name,
va_end (args); 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; return signal_id;
} }
@ -1480,8 +1519,7 @@ signal_add_class_closure (SignalNode *node,
{ {
ClassClosure key; ClassClosure key;
/* can't optimize NOP emissions with overridden class closures */ node->single_va_closure_is_valid = FALSE;
node->test_class_offset = 0;
if (!node->class_closure_bsa) if (!node->class_closure_bsa)
node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig); node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig);
@ -1492,7 +1530,11 @@ signal_add_class_closure (SignalNode *node,
&key); &key);
g_closure_sink (closure); g_closure_sink (closure);
if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (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; gchar *name;
guint signal_id, i; guint signal_id, i;
SignalNode *node; SignalNode *node;
GSignalCMarshaller builtin_c_marshaller;
GSignalCVaMarshaller va_marshaller;
g_return_val_if_fail (signal_name != NULL, 0); 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); 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)); TRACE(GOBJECT_SIGNAL_NEW(signal_id, name, itype));
} }
node->destroyed = FALSE; node->destroyed = FALSE;
node->test_class_offset = 0;
/* setup reinitializable portion */ /* setup reinitializable portion */
node->single_va_closure_is_valid = FALSE;
node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; node->flags = signal_flags & G_SIGNAL_FLAGS_MASK;
node->n_params = n_params; node->n_params = n_params;
node->param_types = g_memdup (param_types, sizeof (GType) * 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 else
node->accumulator = NULL; 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) 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->c_marshaller = c_marshaller;
node->va_marshaller = va_marshaller;
node->emission_hooks = NULL; node->emission_hooks = NULL;
if (class_closure) if (class_closure)
signal_add_class_closure (node, 0, 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 (); SIGNAL_UNLOCK ();
g_free (name); g_free (name);
@ -1665,6 +1753,35 @@ g_signal_newv (const gchar *signal_name,
return signal_id; 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: * g_signal_new_valist:
* @signal_name: the name for the signal * @signal_name: the name for the signal
@ -1734,13 +1851,14 @@ signal_destroy_R (SignalNode *signal_node)
signal_node->destroyed = TRUE; signal_node->destroyed = TRUE;
/* reentrancy caution, zero out real contents first */ /* 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->n_params = 0;
signal_node->param_types = NULL; signal_node->param_types = NULL;
signal_node->return_type = 0; signal_node->return_type = 0;
signal_node->class_closure_bsa = NULL; signal_node->class_closure_bsa = NULL;
signal_node->accumulator = NULL; signal_node->accumulator = NULL;
signal_node->c_marshaller = NULL; signal_node->c_marshaller = NULL;
signal_node->va_marshaller = NULL;
signal_node->emission_hooks = NULL; signal_node->emission_hooks = NULL;
#ifdef G_ENABLE_DEBUG #ifdef G_ENABLE_DEBUG
@ -2166,7 +2284,11 @@ g_signal_connect_closure_by_id (gpointer instance,
g_closure_sink (closure); g_closure_sink (closure);
handler_insert (signal_id, instance, handler); handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) 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 else
@ -2224,7 +2346,11 @@ g_signal_connect_closure (gpointer instance,
g_closure_sink (closure); g_closure_sink (closure);
handler_insert (signal_id, instance, handler); handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 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 else
@ -2318,8 +2444,12 @@ g_signal_connect_data (gpointer instance,
g_closure_sink (handler->closure); g_closure_sink (handler->closure);
handler_insert (signal_id, instance, handler); handler_insert (signal_id, instance, handler);
if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 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 else
g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 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; 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: * g_signal_emitv:
* @instance_and_params: (array): argument list for the signal emission. * @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 */ #endif /* G_ENABLE_DEBUG */
/* optimize NOP emissions */ /* 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 */ HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
SIGNAL_UNLOCK (); if (hlist == NULL || hlist->handlers == NULL)
/* g_printerr ("omitting emission of \"%s\"\n", node->name); */ {
return; /* nothing to do to emit this signal */
SIGNAL_UNLOCK ();
/* g_printerr ("omitting emission of \"%s\"\n", node->name); */
return;
}
} }
SIGNAL_UNLOCK (); SIGNAL_UNLOCK ();
signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params); 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: * g_signal_emit_valist:
* @instance: the instance the signal is being emitted on. * @instance: the instance the signal is being emitted on.
@ -2983,13 +3100,158 @@ g_signal_emit_valist (gpointer instance,
} }
#endif /* !G_DISABLE_CHECKS */ #endif /* !G_DISABLE_CHECKS */
/* optimize NOP emissions */ if (!node->single_va_closure_is_valid)
if (signal_check_skip_emission (node, instance, detail)) 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 */ HandlerList* hlist = handler_list_lookup (node->signal_id, instance);
SIGNAL_UNLOCK (); Handler *l;
/* g_printerr ("omitting emission of \"%s\"\n", node->name); */ GClosure *closure = NULL;
return; 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; 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); 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 static gboolean
signal_emit_unlocked_R (SignalNode *node, signal_emit_unlocked_R (SignalNode *node,
GQuark detail, GQuark detail,

View File

@ -43,6 +43,14 @@ typedef struct _GSignalInvocationHint GSignalInvocationHint;
* signal system. * signal system.
*/ */
typedef GClosureMarshal GSignalCMarshaller; 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: * GSignalEmissionHook:
* @ihint: Signal invocation hint, see #GSignalInvocationHint. * @ihint: Signal invocation hint, see #GSignalInvocationHint.
@ -294,6 +302,9 @@ guint g_signal_new_class_handler (const gchar *signal_name,
GType return_type, GType return_type,
guint n_params, 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, void g_signal_emitv (const GValue *instance_and_params,
guint signal_id, guint signal_id,

View File

@ -24,9 +24,23 @@
#define __G_TYPE_PRIVATE_H__ #define __G_TYPE_PRIVATE_H__
#include "gboxed.h" #include "gboxed.h"
#include "gclosure.h"
G_BEGIN_DECLS 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_c_init (void); /* sync with gvalue.c */
void _g_value_types_init (void); /* sync with gvaluetypes.c */ void _g_value_types_init (void); /* sync with gvaluetypes.c */
void _g_enum_types_init (void); /* sync with genums.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, GBoxedCopyFunc copy_func,
GBoxedFreeFunc free_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 G_END_DECLS
#endif /* __G_TYPE_PRIVATE_H__ */ #endif /* __G_TYPE_PRIVATE_H__ */

View File

@ -158,6 +158,36 @@ G_STMT_START { \
G_VALUE_COLLECT_INIT(value, _value_type, var_args, flags, __error); \ G_VALUE_COLLECT_INIT(value, _value_type, var_args, flags, __error); \
} G_STMT_END } 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: * G_VALUE_LCOPY:
* @value: a #GValue return location. @value is supposed to be initialized * @value: a #GValue return location. @value is supposed to be initialized

View File

@ -9,3 +9,4 @@ reference
signals signals
threadtests threadtests
valuearray valuearray
marshalers.[ch]

View File

@ -18,4 +18,17 @@ TEST_PROGS += \
ifaceproperties \ ifaceproperties \
valuearray 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 ifaceproperties_SOURCES = ifaceproperties.c testcommon.h
EXTRA_DIST += marshalers.list

View File

@ -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

View File

@ -1,4 +1,5 @@
#include <glib-object.h> #include <glib-object.h>
#include "marshalers.h"
typedef enum { typedef enum {
TEST_ENUM_NEGATIVE = -30, 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 _Test Test;
typedef struct _TestClass TestClass; typedef struct _TestClass TestClass;
@ -63,11 +80,15 @@ struct _Test
GObject parent_instance; 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 struct _TestClass
{ {
GObjectClass parent_class; GObjectClass parent_class;
void (* variant_changed) (Test *, GVariant *); 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); static GType test_get_type (void);
@ -81,9 +102,16 @@ test_init (Test *test)
static void static void
test_class_init (TestClass *klass) 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_signal_new ("generic-marshaller-1",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, NULL, 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_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_signal_new ("generic-marshaller-2",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, NULL, 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_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_signal_new ("generic-marshaller-enum-return-signed",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, NULL, NULL,
NULL, NULL,
@ -109,7 +137,7 @@ test_class_init (TestClass *klass)
0); 0);
g_signal_new ("generic-marshaller-enum-return-unsigned", g_signal_new ("generic-marshaller-enum-return-unsigned",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, NULL, NULL,
NULL, NULL,
@ -117,20 +145,40 @@ test_class_init (TestClass *klass)
0); 0);
g_signal_new ("generic-marshaller-int-return", g_signal_new ("generic-marshaller-int-return",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, NULL, NULL,
NULL, NULL,
G_TYPE_INT, G_TYPE_INT,
0); 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_signal_new ("generic-marshaller-uint-return",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST,
0, 0,
NULL, NULL, NULL, NULL,
NULL, NULL,
G_TYPE_UINT, G_TYPE_UINT,
0); 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_signal_new ("variant-changed-no-slot",
G_TYPE_FROM_CLASS (klass), G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT,
@ -149,6 +197,144 @@ test_class_init (TestClass *klass)
G_TYPE_NONE, G_TYPE_NONE,
1, 1,
G_TYPE_VARIANT); 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 static void
@ -371,6 +557,27 @@ test_generic_marshaller_signal_int_return (void)
g_assert_cmpint (retval, ==, 2); g_assert_cmpint (retval, ==, 2);
g_signal_handler_disconnect (test, id); 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); g_object_unref (test);
} }
@ -412,7 +619,146 @@ test_generic_marshaller_signal_uint_return (void)
g_assert_cmpint (retval, ==, G_MAXUINT); g_assert_cmpint (retval, ==, G_MAXUINT);
g_signal_handler_disconnect (test, id); 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_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/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-1", test_generic_marshaller_signal_1);
g_test_add_func ("/gobject/signals/generic-marshaller-2", test_generic_marshaller_signal_2); g_test_add_func ("/gobject/signals/generic-marshaller-2", test_generic_marshaller_signal_2);

View File

@ -234,6 +234,7 @@ struct _ComplexObjectClass
GObjectClass parent_class; GObjectClass parent_class;
void (*signal) (ComplexObject *obj); void (*signal) (ComplexObject *obj);
void (*signal_empty) (ComplexObject *obj);
}; };
static void complex_test_iface_init (gpointer g_iface, static void complex_test_iface_init (gpointer g_iface,
@ -263,6 +264,9 @@ enum {
enum { enum {
COMPLEX_SIGNAL, COMPLEX_SIGNAL,
COMPLEX_SIGNAL_EMPTY,
COMPLEX_SIGNAL_GENERIC,
COMPLEX_SIGNAL_GENERIC_EMPTY,
COMPLEX_LAST_SIGNAL COMPLEX_LAST_SIGNAL
}; };
@ -331,6 +335,7 @@ complex_object_class_init (ComplexObjectClass *class)
object_class->finalize = complex_object_finalize; object_class->finalize = complex_object_finalize;
object_class->set_property = complex_object_set_property; object_class->set_property = complex_object_set_property;
object_class->get_property = complex_object_get_property; object_class->get_property = complex_object_get_property;
class->signal = complex_object_real_signal; class->signal = complex_object_real_signal;
complex_signals[COMPLEX_SIGNAL] = complex_signals[COMPLEX_SIGNAL] =
@ -342,6 +347,32 @@ complex_object_class_init (ComplexObjectClass *class)
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0); G_TYPE_NONE, 0);
complex_signals[COMPLEX_SIGNAL_EMPTY] =
g_signal_new ("signal-empty",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ComplexObjectClass, signal_empty),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
complex_signals[COMPLEX_SIGNAL_GENERIC] =
g_signal_new ("signal-generic",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ComplexObjectClass, signal),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
complex_signals[COMPLEX_SIGNAL_GENERIC_EMPTY] =
g_signal_new ("signal-generic-empty",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (ComplexObjectClass, signal_empty),
NULL, NULL,
NULL,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_VAL1, PROP_VAL1,
g_param_spec_int ("val1", g_param_spec_int ("val1",
@ -560,7 +591,7 @@ test_type_check_teardown (PerformanceTest *test,
} }
/************************************************************* /*************************************************************
* Test signal emissions performance * Test signal unhandled emissions performance
*************************************************************/ *************************************************************/
#define NUM_EMISSIONS_PER_ROUND 10000 #define NUM_EMISSIONS_PER_ROUND 10000
@ -568,22 +599,24 @@ test_type_check_teardown (PerformanceTest *test,
struct EmissionTest { struct EmissionTest {
GObject *object; GObject *object;
int n_checks; int n_checks;
int signal_id;
}; };
static gpointer static gpointer
test_emission_setup (PerformanceTest *test) test_emission_unhandled_setup (PerformanceTest *test)
{ {
struct EmissionTest *data; struct EmissionTest *data;
data = g_new0 (struct EmissionTest, 1); data = g_new0 (struct EmissionTest, 1);
data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL); data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL);
data->signal_id = complex_signals[GPOINTER_TO_INT (test->extra_data)];
return data; return data;
} }
static void static void
test_emission_init (PerformanceTest *test, test_emission_unhandled_init (PerformanceTest *test,
gpointer _data, gpointer _data,
double factor) double factor)
{ {
struct EmissionTest *data = _data; struct EmissionTest *data = _data;
@ -591,8 +624,8 @@ test_emission_init (PerformanceTest *test,
} }
static void static void
test_emission_run (PerformanceTest *test, test_emission_unhandled_run (PerformanceTest *test,
gpointer _data) gpointer _data)
{ {
struct EmissionTest *data = _data; struct EmissionTest *data = _data;
GObject *object = data->object; GObject *object = data->object;
@ -600,20 +633,20 @@ test_emission_run (PerformanceTest *test,
for (i = 0; i < data->n_checks; i++) for (i = 0; i < data->n_checks; i++)
g_signal_emit (object, g_signal_emit (object,
complex_signals[COMPLEX_SIGNAL], data->signal_id,
0); 0);
} }
static void static void
test_emission_finish (PerformanceTest *test, test_emission_unhandled_finish (PerformanceTest *test,
gpointer data) gpointer data)
{ {
} }
static void static void
test_emission_print_result (PerformanceTest *test, test_emission_unhandled_print_result (PerformanceTest *test,
gpointer _data, gpointer _data,
double time) double time)
{ {
struct EmissionTest *data = _data; struct EmissionTest *data = _data;
@ -622,8 +655,8 @@ test_emission_print_result (PerformanceTest *test,
} }
static void static void
test_emission_teardown (PerformanceTest *test, test_emission_unhandled_teardown (PerformanceTest *test,
gpointer _data) gpointer _data)
{ {
struct EmissionTest *data = _data; struct EmissionTest *data = _data;
@ -631,7 +664,89 @@ test_emission_teardown (PerformanceTest *test,
g_free (data); g_free (data);
} }
/*************************************************************
* Test signal handled emissions performance
*************************************************************/
static void
test_emission_handled_handler (ComplexObject *obj, gpointer data)
{
}
static gpointer
test_emission_handled_setup (PerformanceTest *test)
{
struct EmissionTest *data;
data = g_new0 (struct EmissionTest, 1);
data->object = g_object_new (COMPLEX_TYPE_OBJECT, NULL);
data->signal_id = complex_signals[GPOINTER_TO_INT (test->extra_data)];
g_signal_connect (data->object, "signal",
G_CALLBACK (test_emission_handled_handler),
NULL);
g_signal_connect (data->object, "signal-empty",
G_CALLBACK (test_emission_handled_handler),
NULL);
g_signal_connect (data->object, "signal-generic",
G_CALLBACK (test_emission_handled_handler),
NULL);
g_signal_connect (data->object, "signal-generic-empty",
G_CALLBACK (test_emission_handled_handler),
NULL);
return data;
}
static void
test_emission_handled_init (PerformanceTest *test,
gpointer _data,
double factor)
{
struct EmissionTest *data = _data;
data->n_checks = factor * NUM_EMISSIONS_PER_ROUND;
}
static void
test_emission_handled_run (PerformanceTest *test,
gpointer _data)
{
struct EmissionTest *data = _data;
GObject *object = data->object;
int i;
for (i = 0; i < data->n_checks; i++)
g_signal_emit (object,
data->signal_id,
0);
}
static void
test_emission_handled_finish (PerformanceTest *test,
gpointer data)
{
}
static void
test_emission_handled_print_result (PerformanceTest *test,
gpointer _data,
double time)
{
struct EmissionTest *data = _data;
g_print ("Emissions per second: %.0f\n",
data->n_checks / time);
}
static void
test_emission_handled_teardown (PerformanceTest *test,
gpointer _data)
{
struct EmissionTest *data = _data;
g_object_unref (data->object);
g_free (data);
}
/************************************************************* /*************************************************************
* Main test code * Main test code
@ -669,14 +784,84 @@ static PerformanceTest tests[] = {
test_type_check_print_result test_type_check_print_result
}, },
{ {
"emit", "emit-unhandled",
NULL, GINT_TO_POINTER (COMPLEX_SIGNAL),
test_emission_setup, test_emission_unhandled_setup,
test_emission_init, test_emission_unhandled_init,
test_emission_run, test_emission_unhandled_run,
test_emission_finish, test_emission_unhandled_finish,
test_emission_teardown, test_emission_unhandled_teardown,
test_emission_print_result test_emission_unhandled_print_result
},
{
"emit-unhandled-empty",
GINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY),
test_emission_unhandled_setup,
test_emission_unhandled_init,
test_emission_unhandled_run,
test_emission_unhandled_finish,
test_emission_unhandled_teardown,
test_emission_unhandled_print_result
},
{
"emit-unhandled-generic",
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC),
test_emission_unhandled_setup,
test_emission_unhandled_init,
test_emission_unhandled_run,
test_emission_unhandled_finish,
test_emission_unhandled_teardown,
test_emission_unhandled_print_result
},
{
"emit-unhandled-generic-empty",
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY),
test_emission_unhandled_setup,
test_emission_unhandled_init,
test_emission_unhandled_run,
test_emission_unhandled_finish,
test_emission_unhandled_teardown,
test_emission_unhandled_print_result
},
{
"emit-handled",
GINT_TO_POINTER (COMPLEX_SIGNAL),
test_emission_handled_setup,
test_emission_handled_init,
test_emission_handled_run,
test_emission_handled_finish,
test_emission_handled_teardown,
test_emission_handled_print_result
},
{
"emit-handled-empty",
GINT_TO_POINTER (COMPLEX_SIGNAL_EMPTY),
test_emission_handled_setup,
test_emission_handled_init,
test_emission_handled_run,
test_emission_handled_finish,
test_emission_handled_teardown,
test_emission_handled_print_result
},
{
"emit-handled-generic",
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC),
test_emission_handled_setup,
test_emission_handled_init,
test_emission_handled_run,
test_emission_handled_finish,
test_emission_handled_teardown,
test_emission_handled_print_result
},
{
"emit-handled-generic-empty",
GINT_TO_POINTER (COMPLEX_SIGNAL_GENERIC_EMPTY),
test_emission_handled_setup,
test_emission_handled_init,
test_emission_handled_run,
test_emission_handled_finish,
test_emission_handled_teardown,
test_emission_handled_print_result
} }
}; };