From 83c45024e3d3a56ac17eb08dcddae048005bbb71 Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Sun, 5 Nov 2000 05:07:26 +0000 Subject: [PATCH] fixed a bag full of subtle bugs of immensive screw-up potential in Sun Nov 5 05:22:55 2000 Tim Janik * gsignal.c: fixed a bag full of subtle bugs of immensive screw-up potential in handlers_find(), luckily no one found out about them yet ;) fixed signal_handlers_foreach_matched_R() so it operates on an initial handler list snapshot provided by handlers_find() to work around general reentrancy problems and to avoid multiple callback() invocations on the same handlers. this code is now officially 80% bug free (10% remaining for interface types, and 10% remaining for destroyed signals ;) Sat Nov 4 02:01:33 2000 Tim Janik * gsignal.c (_g_signals_destroy): valid signal nodes start out at 1. * gtypeplugin.[hc]: new files holding a GTypePlugin interface implementation that provides the API required by GType to deal with dynamically loadable types. * gtype.[hc]: displace any GTypePlugin business to gtypeplugin.h. --- glib-object.h | 1 + glib/glib-object.h | 1 + gobject/ChangeLog | 22 +++ gobject/Makefile.am | 2 + gobject/gobject.c | 2 +- gobject/gsignal.c | 324 ++++++++++++++++++++++++++---------------- gobject/gsignal.h | 2 +- gobject/gtype.c | 39 ++--- gobject/gtype.h | 26 +--- gobject/gtypeplugin.c | 100 +++++++++++++ gobject/gtypeplugin.h | 85 +++++++++++ 11 files changed, 428 insertions(+), 176 deletions(-) create mode 100644 gobject/gtypeplugin.c create mode 100644 gobject/gtypeplugin.h diff --git a/glib-object.h b/glib-object.h index 92d9bf92f..87ec20684 100644 --- a/glib-object.h +++ b/glib-object.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/glib/glib-object.h b/glib/glib-object.h index 92d9bf92f..87ec20684 100644 --- a/glib/glib-object.h +++ b/glib/glib-object.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include diff --git a/gobject/ChangeLog b/gobject/ChangeLog index 3ad2312fc..5e77f11a8 100644 --- a/gobject/ChangeLog +++ b/gobject/ChangeLog @@ -1,3 +1,25 @@ +Sun Nov 5 05:22:55 2000 Tim Janik + + * gsignal.c: + fixed a bag full of subtle bugs of immensive screw-up potential in + handlers_find(), luckily no one found out about them yet ;) + fixed signal_handlers_foreach_matched_R() so it operates on an + initial handler list snapshot provided by handlers_find() to work + around general reentrancy problems and to avoid multiple callback() + invocations on the same handlers. + this code is now officially 80% bug free (10% remaining for interface + types, and 10% remaining for destroyed signals ;) + +Sat Nov 4 02:01:33 2000 Tim Janik + + * gsignal.c (_g_signals_destroy): valid signal nodes start out at 1. + + * gtypeplugin.[hc]: new files holding a GTypePlugin interface + implementation that provides the API required by GType to deal with + dynamically loadable types. + + * gtype.[hc]: displace any GTypePlugin business to gtypeplugin.h. + Fri Nov 3 07:35:00 2000 Tim Janik * gsignal.[hc]: prefix internal functions with '_'. renamed diff --git a/gobject/Makefile.am b/gobject/Makefile.am index 150796158..4b8e658c2 100644 --- a/gobject/Makefile.am +++ b/gobject/Makefile.am @@ -32,6 +32,7 @@ gobject_public_h_sources = @STRIP_BEGIN@ \ gparamspecs.h \ gsignal.h \ gtype.h \ + gtypeplugin.h \ gvalue.h \ gvaluecollector.h \ gvaluetypes.h \ @@ -51,6 +52,7 @@ gobject_c_sources = @STRIP_BEGIN@ \ gparamspecs.c \ gsignal.c \ gtype.c \ + gtypeplugin.c \ gvalue.c \ gvaluetypes.c \ @STRIP_END@ diff --git a/gobject/gobject.c b/gobject/gobject.c index 7307cbb5f..c4dd8601c 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -295,7 +295,7 @@ g_object_do_shutdown (GObject *object) static void g_object_do_finalize (GObject *object) { - _g_signal_handlers_destroy (object); + g_signal_handlers_destroy (object); g_datalist_clear (&object->qdata); #ifdef DEBUG_OBJECTS diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 051ff8e49..841c329f8 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -73,11 +73,12 @@ g_generic_node_free (GTrashStack **trash_stack_p, /* --- typedefs --- */ -typedef struct _SignalNode SignalNode; -typedef struct _SignalKey SignalKey; -typedef struct _Emission Emission; -typedef struct _Handler Handler; -typedef struct _HandlerList HandlerList; +typedef struct _SignalNode SignalNode; +typedef struct _SignalKey SignalKey; +typedef struct _Emission Emission; +typedef struct _Handler Handler; +typedef struct _HandlerList HandlerList; +typedef struct _HandlerMatch HandlerMatch; typedef enum { EMISSION_STOP, @@ -88,47 +89,53 @@ typedef enum /* --- prototypes --- */ -static inline guint signal_id_lookup (GQuark quark, - GType itype); -static void signal_destroy_R (SignalNode *signal_node); -static inline HandlerList* handler_list_ensure (guint signal_id, - gpointer instance); -static inline HandlerList* handler_list_lookup (guint signal_id, - gpointer instance); -static inline Handler* handler_new (gboolean after); -static void handler_insert (guint signal_id, - gpointer instance, - Handler *handler); -static Handler* handler_lookup (gpointer instance, - guint handler_id, - guint *signal_id_p); -static Handler* handler_find (gpointer instance, - GSignalMatchType mask, - guint signal_id, - GQuark detail, - GClosure *closure, - gpointer func, - gpointer data); -static inline void handler_ref (Handler *handler); -static inline void handler_unref_R (guint signal_id, - gpointer instance, - Handler *handler); -static inline void emission_push (Emission **emission_list_p, - guint signal_id, - GQuark detail, - gpointer instance, - EmissionState *state_p); -static inline void emission_pop (Emission **emission_list_p, - EmissionState *state_p); -static inline Emission* emission_find (Emission *emission_list, - guint signal_id, - GQuark detail, - gpointer instance); -static void signal_emit_R (SignalNode *node, - GQuark detail, - gpointer instance, - GValue *return_value, - const GValue *instance_and_params); +static inline guint signal_id_lookup (GQuark quark, + GType itype); +static void signal_destroy_R (SignalNode *signal_node); +static inline HandlerList* handler_list_ensure (guint signal_id, + gpointer instance); +static inline HandlerList* handler_list_lookup (guint signal_id, + gpointer instance); +static inline Handler* handler_new (gboolean after); +static void handler_insert (guint signal_id, + gpointer instance, + Handler *handler); +static Handler* handler_lookup (gpointer instance, + guint handler_id, + guint *signal_id_p); +static inline HandlerMatch* handler_match_prepend (HandlerMatch *list, + Handler *handler, + guint signal_id); +static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node, + gpointer instance); +static HandlerMatch* handlers_find (gpointer instance, + GSignalMatchType mask, + guint signal_id, + GQuark detail, + GClosure *closure, + gpointer func, + gpointer data, + gboolean one_and_only); +static inline void handler_ref (Handler *handler); +static inline void handler_unref_R (guint signal_id, + gpointer instance, + Handler *handler); +static inline void emission_push (Emission **emission_list_p, + guint signal_id, + GQuark detail, + gpointer instance, + EmissionState *state_p); +static inline void emission_pop (Emission **emission_list_p, + EmissionState *state_p); +static inline Emission* emission_find (Emission *emission_list, + guint signal_id, + GQuark detail, + gpointer instance); +static void signal_emit_R (SignalNode *node, + GQuark detail, + gpointer instance, + GValue *return_value, + const GValue *instance_and_params); /* --- structures --- */ @@ -172,7 +179,6 @@ struct _HandlerList guint signal_id; Handler *handlers; }; - struct _Handler { guint id; @@ -186,6 +192,15 @@ struct _Handler guint after : 1; GClosure *closure; }; +struct _HandlerMatch +{ + Handler *handler; + HandlerMatch *next; + union { + guint signal_id; + gpointer dummy; + } d; +}; /* --- variables --- */ @@ -313,15 +328,50 @@ handler_lookup (gpointer instance, return NULL; } -static Handler* -handler_find (gpointer instance, - GSignalMatchType mask, - guint signal_id, - GQuark detail, - GClosure *closure, - gpointer func, - gpointer data) +static inline HandlerMatch* +handler_match_prepend (HandlerMatch *list, + Handler *handler, + guint signal_id) { + HandlerMatch *node; + + /* yeah, we could use our own memchunk here, introducing yet more + * rarely used cached nodes and extra allocation overhead. + * instead, we use GList* nodes, since they are exactly the size + * we need and are already cached. g_signal_init() asserts this. + */ + node = (HandlerMatch*) g_list_alloc (); + node->handler = handler; + node->next = list; + node->d.signal_id = signal_id; + handler_ref (handler); + + return node; +} +static inline HandlerMatch* +handler_match_free1_R (HandlerMatch *node, + gpointer instance) +{ + HandlerMatch *next = node->next; + + handler_unref_R (node->d.signal_id, instance, node->handler); + g_list_free_1 ((GList*) node); + + return next; +} + +static HandlerMatch* +handlers_find (gpointer instance, + GSignalMatchType mask, + guint signal_id, + GQuark detail, + GClosure *closure, + gpointer func, + gpointer data, + gboolean one_and_only) +{ + HandlerMatch *mlist = NULL; + if (mask & G_SIGNAL_MATCH_ID) { HandlerList *hlist = handler_list_lookup (signal_id, instance); @@ -334,17 +384,22 @@ handler_find (gpointer instance, if (!node || !node->c_marshaller) return NULL; } - + mask = ~mask; for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) - if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && + if (handler->id && + ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && ((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 && ((GCClosure*) handler->closure)->callback == func))) - return handler; + { + mlist = handler_match_prepend (mlist, handler, signal_id); + if (one_and_only) + return mlist; + } } else { @@ -367,21 +422,26 @@ handler_find (gpointer instance, if (!node->c_marshaller) continue; } - + for (handler = hlist->handlers; handler; handler = handler->next) - if (((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && + if (handler->id && + ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && ((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 && ((GCClosure*) handler->closure)->callback == func))) - return handler; + { + mlist = handler_match_prepend (mlist, handler, signal_id); + if (one_and_only) + return mlist; + } } } } - return NULL; + return mlist; } static inline Handler* @@ -433,7 +493,7 @@ handler_unref_R (guint signal_id, { if (handler->next) handler->next->prev = handler->prev; - if (handler->prev) /* watch out for _g_signal_handlers_destroy()! */ + if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ handler->prev->next = handler->next; else { @@ -507,7 +567,7 @@ emission_pop (Emission **emission_list_p, EmissionState *state_p) { Emission **loc = emission_list_p, *emission = *loc; - + while (emission->state_p != state_p) { loc = &emission->next; @@ -551,6 +611,9 @@ g_signal_init (void) /* sync with gtype.c */ G_LOCK (g_signal_mutex); if (!g_n_signal_nodes) { + /* handler_id_node_prepend() requires this */ + g_assert (sizeof (GList) == sizeof (HandlerMatch)); + /* setup signal key array */ g_signal_key_bsa.cmp_func = signal_key_cmp; g_signal_key_bsa.sizeof_node = sizeof (SignalKey); @@ -573,7 +636,7 @@ _g_signals_destroy (GType itype) guint i; G_LOCK (g_signal_mutex); - for (i = 0; i < g_n_signal_nodes; i++) + for (i = 1; i < g_n_signal_nodes; i++) { SignalNode *node = g_signal_nodes[i]; @@ -683,21 +746,21 @@ g_signal_parse_name (const gchar *detailed_signal, { GQuark detail = 0; guint signal_id; - + g_return_val_if_fail (detailed_signal != NULL, FALSE); g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); - + G_LOCK (g_signal_mutex); signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); G_UNLOCK (g_signal_mutex); - + if (signal_id) { if (signal_id_p) *signal_id_p = signal_id; if (detail_p) *detail_p = detail; - + return TRUE; } else @@ -725,7 +788,7 @@ g_signal_name (guint signal_id) { SignalNode *node; gchar *name; - + G_LOCK (g_signal_mutex); node = LOOKUP_SIGNAL_NODE (signal_id); name = node ? node->name : NULL; @@ -739,9 +802,9 @@ g_signal_query (guint signal_id, GSignalQuery *query) { SignalNode *node; - + g_return_if_fail (query != NULL); - + G_LOCK (g_signal_mutex); node = LOOKUP_SIGNAL_NODE (signal_id); if (!node || node->destroyed) @@ -767,12 +830,12 @@ g_signal_list_ids (GType itype, GArray *result; guint n_nodes; guint i; - + g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); g_return_val_if_fail (n_ids != NULL, NULL); - + G_LOCK (g_signal_mutex); - + keys = g_signal_key_bsa.nodes; n_nodes = g_signal_key_bsa.n_nodes; result = g_array_new (FALSE, FALSE, sizeof (guint)); @@ -781,16 +844,16 @@ g_signal_list_ids (GType itype, if (keys[i].itype == itype) { gchar *name = g_quark_to_string (keys[i].quark); - + /* Signal names with "_" in them are aliases to the same * name with "-" instead of "_". */ if (!strchr (name, '_')) g_array_append_val (result, keys[i].signal_id); } - + *n_ids = result->len; - + G_UNLOCK (g_signal_mutex); return (guint *) g_array_free (result, FALSE); @@ -1056,7 +1119,7 @@ g_signal_handler_disconnect (gpointer instance, } void -_g_signal_handlers_destroy (gpointer instance) +g_signal_handlers_destroy (gpointer instance) { GBSearchArray *hlbsa; @@ -1070,7 +1133,7 @@ _g_signal_handlers_destroy (gpointer instance) /* reentrancy caution, delete instance trace first */ g_hash_table_remove (g_handler_list_bsa_ht, instance); - + for (i = 0; i < hlbsa->n_nodes; i++) { HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, i); @@ -1107,48 +1170,52 @@ g_signal_handler_find (gpointer instance, gpointer func, gpointer data) { - Handler *handler; guint handler_id = 0; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); - + if (mask & G_SIGNAL_MATCH_MASK) { + HandlerMatch *mlist; + G_LOCK (g_signal_mutex); - handler = handler_find (instance, mask, signal_id, detail, closure, func, data); - handler_id = handler ? handler->id : 0; + mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); + if (mlist) + { + handler_id = mlist->handler->id; + handler_match_free1_R (mlist, instance); + } G_UNLOCK (g_signal_mutex); } - + return handler_id; } static guint -signal_handlers_foreach_matched (gpointer instance, - GSignalMatchType mask, - guint signal_id, - GQuark detail, - GClosure *closure, - gpointer func, - gpointer data, - void (*callback) (gpointer instance, - guint handler_id)) +signal_handlers_foreach_matched_R (gpointer instance, + GSignalMatchType mask, + guint signal_id, + GQuark detail, + GClosure *closure, + gpointer func, + gpointer data, + void (*callback) (gpointer instance, + guint handler_id)) { - Handler *handler; + HandlerMatch *mlist; guint n_handlers = 0; - - handler = handler_find (instance, mask, signal_id, detail, closure, func, data); - while (handler && handler->id) + + mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); + while (mlist) { n_handlers++; G_UNLOCK (g_signal_mutex); - callback (instance, handler->id); + callback (instance, mlist->handler->id); G_LOCK (g_signal_mutex); - /* need constant relookups due to callback */ - handler = handler_find (instance, mask, signal_id, detail, closure, func, data); + mlist = handler_match_free1_R (mlist, instance); } - + return n_handlers; } @@ -1162,19 +1229,19 @@ g_signal_handlers_block_matched (gpointer instance, gpointer data) { guint n_handlers = 0; - + g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); - + if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { G_LOCK (g_signal_mutex); - n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_block); + n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, + closure, func, data, + g_signal_handler_block); G_UNLOCK (g_signal_mutex); } - + return n_handlers; } @@ -1195,12 +1262,12 @@ g_signal_handlers_unblock_matched (gpointer instance, if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { G_LOCK (g_signal_mutex); - n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_unblock); + n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, + closure, func, data, + g_signal_handler_unblock); G_UNLOCK (g_signal_mutex); } - + return n_handlers; } @@ -1214,19 +1281,19 @@ g_signal_handlers_disconnect_matched (gpointer instance, gpointer data) { guint n_handlers = 0; - + g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, FALSE); - + if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) { G_LOCK (g_signal_mutex); - n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail, - closure, func, data, - g_signal_handler_disconnect); + n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, + closure, func, data, + g_signal_handler_disconnect); G_UNLOCK (g_signal_mutex); } - + return n_handlers; } @@ -1236,7 +1303,8 @@ g_signal_has_handler_pending (gpointer instance, GQuark detail, gboolean may_be_blocked) { - Handler *handler = NULL; + HandlerMatch *mlist; + gboolean has_pending; g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); g_return_val_if_fail (signal_id > 0, FALSE); @@ -1253,13 +1321,19 @@ g_signal_has_handler_pending (gpointer instance, return FALSE; } } - handler = handler_find (instance, - (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | - (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), - signal_id, detail, NULL, NULL, NULL); + mlist = handlers_find (instance, + (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), + signal_id, detail, NULL, NULL, NULL, TRUE); + if (mlist) + { + has_pending = TRUE; + handler_match_free1_R (mlist, instance); + } + else + has_pending = FALSE; G_UNLOCK (g_signal_mutex); - return handler != NULL; + return has_pending; } void @@ -1277,7 +1351,7 @@ g_signal_emitv (const GValue *instance_and_params, instance = g_value_get_as_pointer (instance_and_params); g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); g_return_if_fail (signal_id > 0); - + param_values = instance_and_params + 1; G_LOCK (g_signal_mutex); diff --git a/gobject/gsignal.h b/gobject/gsignal.h index 7c2caa049..9d2c5ca7c 100644 --- a/gobject/gsignal.h +++ b/gobject/gsignal.h @@ -169,7 +169,7 @@ gboolean g_signal_parse_name (const gchar *detailed_signal, guint *signal_id_p, GQuark *detail_p, gboolean force_detail_quark); -void _g_signal_handlers_destroy (gpointer instance); +void g_signal_handlers_destroy (gpointer instance); void _g_signals_destroy (GType itype); diff --git a/gobject/gtype.c b/gobject/gtype.c index 5b055b372..a288b657b 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -18,6 +18,7 @@ */ #include "gtype.h" +#include "gtypeplugin.h" #include #define FIXME_DISABLE_PREALLOCATIONS @@ -45,10 +46,6 @@ G_TYPE_FLAG_DEEP_DERIVABLE) #define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT) -#define g_type_plugin_ref(p) ((p)->vtable->plugin_ref (p)) -#define g_type_plugin_unref(p) ((p)->vtable->plugin_unref (p)) -#define g_type_plugin_complete_type_info(p,t,i,v) ((p)->vtable->complete_type_info ((p), (t), (i), (v))) -#define g_type_plugin_complete_interface_info(p,f,t,i) ((p)->vtable->complete_interface_info ((p), (f), (t), (i))) /* --- typedefs --- */ @@ -398,31 +395,19 @@ check_plugin (GTypePlugin *plugin, type_name); return FALSE; } - if (!plugin->vtable) + if (!G_IS_TYPE_PLUGIN (plugin)) { - g_warning ("plugin for type `%s' has no function table", - type_name); + g_warning ("plugin pointer (%p) for type `%s' is invalid", + plugin, type_name); return FALSE; } - if (!plugin->vtable->plugin_ref) - { - g_warning ("plugin for type `%s' has no plugin_ref() implementation", - type_name); - return FALSE; - } - if (!plugin->vtable->plugin_unref) - { - g_warning ("plugin for type `%s' has no plugin_unref() implementation", - type_name); - return FALSE; - } - if (need_complete_type_info && !plugin->vtable->complete_type_info) + if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info) { g_warning ("plugin for type `%s' has no complete_type_info() implementation", type_name); return FALSE; } - if (need_complete_interface_info && !plugin->vtable->complete_interface_info) + if (need_complete_interface_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_interface_info) { g_warning ("plugin for type `%s' has no complete_interface_info() implementation", type_name); @@ -830,7 +815,7 @@ type_data_ref (TypeNode *node) memset (&tmp_info, 0, sizeof (tmp_info)); memset (&tmp_value_table, 0, sizeof (tmp_value_table)); - g_type_plugin_ref (node->plugin); + g_type_plugin_use (node->plugin); g_type_plugin_complete_type_info (node->plugin, NODE_TYPE (node), &tmp_info, &tmp_value_table); check_type_info (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info); type_data_make (node, &tmp_info, @@ -930,7 +915,7 @@ type_iface_retrive_holder_info (TypeNode *iface, type_data_ref (iface); memset (&tmp_info, 0, sizeof (tmp_info)); - g_type_plugin_ref (iholder->plugin); + g_type_plugin_use (iholder->plugin); g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmp_info); check_interface_info (iface, instance_type, &tmp_info); iholder->info = g_memdup (&tmp_info, sizeof (tmp_info)); @@ -954,7 +939,7 @@ type_iface_blow_holder_info (TypeNode *iface, { g_free (iholder->info); iholder->info = NULL; - g_type_plugin_unref (iholder->plugin); + g_type_plugin_unuse (iholder->plugin); type_data_unref (iface, FALSE); } @@ -1279,7 +1264,7 @@ type_data_last_unref (GType type, if (ptype) type_data_unref (LOOKUP_TYPE_NODE (ptype), FALSE); - g_type_plugin_unref (node->plugin); + g_type_plugin_unuse (node->plugin); } } @@ -2117,6 +2102,10 @@ g_type_init (void) type_data_make (node, &info, NULL); /* FIXME */ g_assert (type == G_TYPE_INTERFACE); + /* G_TYPE_TYPE_PLUGIN + */ + g_type_plugin_get_type (); + /* G_TYPE_* value types */ g_value_types_init (); diff --git a/gobject/gtype.h b/gobject/gtype.h index 1c8e0b40b..bbef767cf 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -116,7 +116,6 @@ typedef guint32 GType; typedef struct _GValue GValue; typedef union _GTypeCValue GTypeCValue; typedef struct _GTypePlugin GTypePlugin; -typedef struct _GTypePluginVTable GTypePluginVTable; typedef struct _GTypeClass GTypeClass; typedef struct _GTypeInterface GTypeInterface; typedef struct _GTypeInstance GTypeInstance; @@ -154,7 +153,7 @@ struct _GTypeInterface #define G_TYPE_CHECK_INSTANCE(instance) (_G_TYPE_CHI ((GTypeInstance*) (instance))) #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type) (_G_TYPE_CIC ((instance), (g_type), c_type)) #define G_TYPE_CHECK_INSTANCE_TYPE(instance, g_type) (_G_TYPE_CIT ((instance), (g_type))) -#define G_TYPE_INSTANCE_GET_CLASS(instance, g_type, c_type) (_G_TYPE_IGC ((instance), c_type)) +#define G_TYPE_INSTANCE_GET_CLASS(instance, g_type, c_type) (_G_TYPE_IGC ((instance), (g_type), c_type)) #define G_TYPE_INSTANCE_GET_INTERFACE(instance, g_type, c_type) (_G_TYPE_IGI ((instance), (g_type), c_type)) #define G_TYPE_CHECK_CLASS_CAST(g_class, g_type, c_type) (_G_TYPE_CCC ((g_class), (g_type), c_type)) #define G_TYPE_CHECK_CLASS_TYPE(g_class, g_type) (_G_TYPE_CCT ((g_class), (g_type))) @@ -210,29 +209,8 @@ typedef void (*GInterfaceInitFunc) (gpointer g_iface, gpointer iface_data); typedef void (*GInterfaceFinalizeFunc) (gpointer g_iface, gpointer iface_data); -typedef void (*GTypePluginRef) (GTypePlugin *plugin); -typedef void (*GTypePluginUnRef) (GTypePlugin *plugin); -typedef void (*GTypePluginFillTypeInfo) (GTypePlugin *plugin, - GType g_type, - GTypeInfo *info, - GTypeValueTable *value_table); -typedef void (*GTypePluginFillInterfaceInfo) (GTypePlugin *plugin, - GType interface_type, - GType instance_type, - GInterfaceInfo *info); typedef gboolean (*GTypeClassCacheFunc) (gpointer cache_data, GTypeClass *g_class); -struct _GTypePlugin -{ - GTypePluginVTable *vtable; -}; -struct _GTypePluginVTable -{ - GTypePluginRef plugin_ref; - GTypePluginUnRef plugin_unref; - GTypePluginFillTypeInfo complete_type_info; - GTypePluginFillInterfaceInfo complete_interface_info; -}; typedef enum /*< skip >*/ { G_TYPE_FLAG_CLASSED = (1 << 0), @@ -359,7 +337,7 @@ GTypeValueTable* g_type_value_table_peek (GType type); #define _G_TYPE_CCT(cp, gt) (g_type_class_is_a ((GTypeClass*) cp, gt)) #define _G_TYPE_CVT(vl, gt) (g_type_value_conforms_to ((GValue*) vl, gt)) #define _G_TYPE_CHV(vl) (g_type_check_value ((GValue*) vl)) -#define _G_TYPE_IGC(ip, ct) ((ct*) (((GTypeInstance*) ip)->g_class)) +#define _G_TYPE_IGC(ip, gt, ct) ((ct*) (((GTypeInstance*) ip)->g_class)) #define _G_TYPE_IGI(ip, gt, ct) ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt)) diff --git a/gobject/gtypeplugin.c b/gobject/gtypeplugin.c new file mode 100644 index 000000000..51da5d8c1 --- /dev/null +++ b/gobject/gtypeplugin.c @@ -0,0 +1,100 @@ +/* GObject - GLib Type, Object, Parameter and Signal Library + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "gtypeplugin.h" + + + +/* --- functions --- */ +GType +g_type_plugin_get_type (void) +{ + static GType type_plugin_type = 0; + + if (!type_plugin_type) + { + static const GTypeInfo type_plugin_info = { + sizeof (GTypePluginClass), + NULL, /* base_init */ + NULL, /* base_finalize */ + }; + + type_plugin_type = g_type_register_static (G_TYPE_INTERFACE, "GTypePlugin", &type_plugin_info, 0); + } + + return type_plugin_type; +} + +void +g_type_plugin_use (GTypePlugin *plugin) +{ + GTypePluginClass *iface; + + g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); + + iface = G_TYPE_PLUGIN_GET_CLASS (plugin); + iface->use_plugin (plugin); +} + +void +g_type_plugin_unuse (GTypePlugin *plugin) +{ + GTypePluginClass *iface; + + g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); + + iface = G_TYPE_PLUGIN_GET_CLASS (plugin); + iface->unuse_plugin (plugin); +} + +void +g_type_plugin_complete_type_info (GTypePlugin *plugin, + GType g_type, + GTypeInfo *info, + GTypeValueTable *value_table) +{ + GTypePluginClass *iface; + + g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); + g_return_if_fail (info != NULL); + g_return_if_fail (value_table != NULL); + + iface = G_TYPE_PLUGIN_GET_CLASS (plugin); + iface->complete_type_info (plugin, + g_type, + info, + value_table); +} + +void +g_type_plugin_complete_interface_info (GTypePlugin *plugin, + GType interface_type, + GType instance_type, + GInterfaceInfo *info) +{ + GTypePluginClass *iface; + + g_return_if_fail (G_IS_TYPE_PLUGIN (plugin)); + g_return_if_fail (info != NULL); + + iface = G_TYPE_PLUGIN_GET_CLASS (plugin); + iface->complete_interface_info (plugin, + interface_type, + instance_type, + info); +} diff --git a/gobject/gtypeplugin.h b/gobject/gtypeplugin.h new file mode 100644 index 000000000..380dd32f4 --- /dev/null +++ b/gobject/gtypeplugin.h @@ -0,0 +1,85 @@ +/* GObject - GLib Type, Object, Parameter and Signal Library + * Copyright (C) 2000 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef __G_TYPE_PLUGIN_H__ +#define __G_TYPE_PLUGIN_H__ + + +#include + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + +/* --- type macros --- */ +#define G_TYPE_TYPE_PLUGIN (g_type_plugin_get_type ()) +#define G_TYPE_PLUGIN(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), G_TYPE_TYPE_PLUGIN, GTypePlugin)) +#define G_TYPE_PLUGIN_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), G_TYPE_TYPE_PLUGIN, GTypePluginClass)) +#define G_IS_TYPE_PLUGIN(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), G_TYPE_TYPE_PLUGIN)) +#define G_IS_TYPE_PLUGIN_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), G_TYPE_TYPE_PLUGIN)) +#define G_TYPE_PLUGIN_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), G_TYPE_TYPE_PLUGIN, GTypePluginClass)) + + +/* --- typedefs & structures --- */ +typedef struct _GTypePluginClass GTypePluginClass; +typedef void (*GTypePluginUse) (GTypePlugin *plugin); +typedef void (*GTypePluginUnuse) (GTypePlugin *plugin); +typedef void (*GTypePluginCompleteTypeInfo) (GTypePlugin *plugin, + GType g_type, + GTypeInfo *info, + GTypeValueTable *value_table); +typedef void (*GTypePluginCompleteInterfaceInfo) (GTypePlugin *plugin, + GType interface_type, + GType instance_type, + GInterfaceInfo *info); +struct _GTypePluginClass +{ + GTypeInterface base_iface; + + GTypePluginUse use_plugin; + GTypePluginUnuse unuse_plugin; + GTypePluginCompleteTypeInfo complete_type_info; + GTypePluginCompleteInterfaceInfo complete_interface_info; +}; + + +/* --- prototypes --- */ +GType g_type_plugin_get_type (void) G_GNUC_CONST; +void g_type_plugin_use (GTypePlugin *plugin); +void g_type_plugin_unuse (GTypePlugin *plugin); +void g_type_plugin_complete_type_info (GTypePlugin *plugin, + GType g_type, + GTypeInfo *info, + GTypeValueTable *value_table); +void g_type_plugin_complete_interface_info (GTypePlugin *plugin, + GType interface_type, + GType instance_type, + GInterfaceInfo *info); + + + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __G_TYPE_PLUGIN_H__ */