From d5fbbe400aef8c802968a1398fc8e9546173b748 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 22 Feb 2012 17:46:21 +0100 Subject: [PATCH] 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 --- gobject/gclosure.c | 81 +++++++++++++++++------------------------ gobject/gclosure.h | 6 ++- gobject/gsignal.c | 4 +- gobject/gtype-private.h | 12 ++++++ 4 files changed, 51 insertions(+), 52 deletions(-) diff --git a/gobject/gclosure.c b/gobject/gclosure.c index 17b7690b2..4c0392a7b 100644 --- a/gobject/gclosure.c +++ b/gobject/gclosure.c @@ -34,6 +34,7 @@ #include "genums.h" #include "gvalue.h" #include "gvaluetypes.h" +#include "gtype-private.h" /** @@ -90,13 +91,11 @@ * */ - #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 { diff --git a/gobject/gclosure.h b/gobject/gclosure.h index bb024a44f..69a584d1e 100644 --- a/gobject/gclosure.h +++ b/gobject/gclosure.h @@ -51,7 +51,7 @@ G_BEGIN_DECLS * * Returns: number of notifiers */ -#define G_CLOSURE_N_NOTIFIERS(cl) ((cl)->meta_marshal + ((cl)->n_guards << 1L) + \ +#define G_CLOSURE_N_NOTIFIERS(cl) (((cl)->n_guards << 1L) + \ (cl)->n_fnotifiers + (cl)->n_inotifiers) /** * G_CCLOSURE_SWAP_DATA: @@ -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 */ diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 573673284..1346929f4 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -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); diff --git a/gobject/gtype-private.h b/gobject/gtype-private.h index 85b6c58ad..bccc9a661 100644 --- a/gobject/gtype-private.h +++ b/gobject/gtype-private.h @@ -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 */