mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-11 23:16:14 +01:00
Add GRealClosure and move meta_marshallers there
This means we're not abusing the notifiers for meta_marshallres, and we're able to later cleanly add other fields to GClosure. We still have to leave the ABI intact for the GClosure->meta_marshal bit, as old G_CLOSURE_N_NOTIFIERS macro instances still accesses it. However, we always set it to zero to keep those macros working. https://bugzilla.gnome.org/show_bug.cgi?id=661140
This commit is contained in:
parent
950e6a4a20
commit
d5fbbe400a
@ -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;
|
||||
@ -325,27 +315,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 +377,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 +580,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 +728,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 +741,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
|
||||
{
|
||||
|
@ -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:
|
||||
@ -149,7 +149,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 */
|
||||
|
@ -502,7 +502,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 +539,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);
|
||||
|
@ -24,9 +24,21 @@
|
||||
#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;
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user