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