fixed a bag full of subtle bugs of immensive screw-up potential in

Sun Nov  5 05:22:55 2000  Tim Janik  <timj@gtk.org>

        * 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  <timj@gtk.org>

        * 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.
This commit is contained in:
Tim Janik 2000-11-05 05:07:26 +00:00 committed by Tim Janik
parent 3cc60a9ab1
commit 83c45024e3
11 changed files with 428 additions and 176 deletions

View File

@ -28,6 +28,7 @@
#include <gobject/gparamspecs.h> #include <gobject/gparamspecs.h>
#include <gobject/gsignal.h> #include <gobject/gsignal.h>
#include <gobject/gtype.h> #include <gobject/gtype.h>
#include <gobject/gtypeplugin.h>
#include <gobject/gvalue.h> #include <gobject/gvalue.h>
#include <gobject/gvaluetypes.h> #include <gobject/gvaluetypes.h>

View File

@ -28,6 +28,7 @@
#include <gobject/gparamspecs.h> #include <gobject/gparamspecs.h>
#include <gobject/gsignal.h> #include <gobject/gsignal.h>
#include <gobject/gtype.h> #include <gobject/gtype.h>
#include <gobject/gtypeplugin.h>
#include <gobject/gvalue.h> #include <gobject/gvalue.h>
#include <gobject/gvaluetypes.h> #include <gobject/gvaluetypes.h>

View File

@ -1,3 +1,25 @@
Sun Nov 5 05:22:55 2000 Tim Janik <timj@gtk.org>
* 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 <timj@gtk.org>
* 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 <timj@gtk.org> Fri Nov 3 07:35:00 2000 Tim Janik <timj@gtk.org>
* gsignal.[hc]: prefix internal functions with '_'. renamed * gsignal.[hc]: prefix internal functions with '_'. renamed

View File

@ -32,6 +32,7 @@ gobject_public_h_sources = @STRIP_BEGIN@ \
gparamspecs.h \ gparamspecs.h \
gsignal.h \ gsignal.h \
gtype.h \ gtype.h \
gtypeplugin.h \
gvalue.h \ gvalue.h \
gvaluecollector.h \ gvaluecollector.h \
gvaluetypes.h \ gvaluetypes.h \
@ -51,6 +52,7 @@ gobject_c_sources = @STRIP_BEGIN@ \
gparamspecs.c \ gparamspecs.c \
gsignal.c \ gsignal.c \
gtype.c \ gtype.c \
gtypeplugin.c \
gvalue.c \ gvalue.c \
gvaluetypes.c \ gvaluetypes.c \
@STRIP_END@ @STRIP_END@

View File

@ -295,7 +295,7 @@ g_object_do_shutdown (GObject *object)
static void static void
g_object_do_finalize (GObject *object) g_object_do_finalize (GObject *object)
{ {
_g_signal_handlers_destroy (object); g_signal_handlers_destroy (object);
g_datalist_clear (&object->qdata); g_datalist_clear (&object->qdata);
#ifdef DEBUG_OBJECTS #ifdef DEBUG_OBJECTS

View File

@ -73,11 +73,12 @@ g_generic_node_free (GTrashStack **trash_stack_p,
/* --- typedefs --- */ /* --- typedefs --- */
typedef struct _SignalNode SignalNode; typedef struct _SignalNode SignalNode;
typedef struct _SignalKey SignalKey; typedef struct _SignalKey SignalKey;
typedef struct _Emission Emission; typedef struct _Emission Emission;
typedef struct _Handler Handler; typedef struct _Handler Handler;
typedef struct _HandlerList HandlerList; typedef struct _HandlerList HandlerList;
typedef struct _HandlerMatch HandlerMatch;
typedef enum typedef enum
{ {
EMISSION_STOP, EMISSION_STOP,
@ -88,47 +89,53 @@ typedef enum
/* --- prototypes --- */ /* --- prototypes --- */
static inline guint signal_id_lookup (GQuark quark, static inline guint signal_id_lookup (GQuark quark,
GType itype); GType itype);
static void signal_destroy_R (SignalNode *signal_node); static void signal_destroy_R (SignalNode *signal_node);
static inline HandlerList* handler_list_ensure (guint signal_id, static inline HandlerList* handler_list_ensure (guint signal_id,
gpointer instance); gpointer instance);
static inline HandlerList* handler_list_lookup (guint signal_id, static inline HandlerList* handler_list_lookup (guint signal_id,
gpointer instance); gpointer instance);
static inline Handler* handler_new (gboolean after); static inline Handler* handler_new (gboolean after);
static void handler_insert (guint signal_id, static void handler_insert (guint signal_id,
gpointer instance, gpointer instance,
Handler *handler); Handler *handler);
static Handler* handler_lookup (gpointer instance, static Handler* handler_lookup (gpointer instance,
guint handler_id, guint handler_id,
guint *signal_id_p); guint *signal_id_p);
static Handler* handler_find (gpointer instance, static inline HandlerMatch* handler_match_prepend (HandlerMatch *list,
GSignalMatchType mask, Handler *handler,
guint signal_id, guint signal_id);
GQuark detail, static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node,
GClosure *closure, gpointer instance);
gpointer func, static HandlerMatch* handlers_find (gpointer instance,
gpointer data); GSignalMatchType mask,
static inline void handler_ref (Handler *handler); guint signal_id,
static inline void handler_unref_R (guint signal_id, GQuark detail,
gpointer instance, GClosure *closure,
Handler *handler); gpointer func,
static inline void emission_push (Emission **emission_list_p, gpointer data,
guint signal_id, gboolean one_and_only);
GQuark detail, static inline void handler_ref (Handler *handler);
gpointer instance, static inline void handler_unref_R (guint signal_id,
EmissionState *state_p); gpointer instance,
static inline void emission_pop (Emission **emission_list_p, Handler *handler);
EmissionState *state_p); static inline void emission_push (Emission **emission_list_p,
static inline Emission* emission_find (Emission *emission_list, guint signal_id,
guint signal_id, GQuark detail,
GQuark detail, gpointer instance,
gpointer instance); EmissionState *state_p);
static void signal_emit_R (SignalNode *node, static inline void emission_pop (Emission **emission_list_p,
GQuark detail, EmissionState *state_p);
gpointer instance, static inline Emission* emission_find (Emission *emission_list,
GValue *return_value, guint signal_id,
const GValue *instance_and_params); GQuark detail,
gpointer instance);
static void signal_emit_R (SignalNode *node,
GQuark detail,
gpointer instance,
GValue *return_value,
const GValue *instance_and_params);
/* --- structures --- */ /* --- structures --- */
@ -172,7 +179,6 @@ struct _HandlerList
guint signal_id; guint signal_id;
Handler *handlers; Handler *handlers;
}; };
struct _Handler struct _Handler
{ {
guint id; guint id;
@ -186,6 +192,15 @@ struct _Handler
guint after : 1; guint after : 1;
GClosure *closure; GClosure *closure;
}; };
struct _HandlerMatch
{
Handler *handler;
HandlerMatch *next;
union {
guint signal_id;
gpointer dummy;
} d;
};
/* --- variables --- */ /* --- variables --- */
@ -313,15 +328,50 @@ handler_lookup (gpointer instance,
return NULL; return NULL;
} }
static Handler* static inline HandlerMatch*
handler_find (gpointer instance, handler_match_prepend (HandlerMatch *list,
GSignalMatchType mask, Handler *handler,
guint signal_id, guint signal_id)
GQuark detail,
GClosure *closure,
gpointer func,
gpointer data)
{ {
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) if (mask & G_SIGNAL_MATCH_ID)
{ {
HandlerList *hlist = handler_list_lookup (signal_id, instance); HandlerList *hlist = handler_list_lookup (signal_id, instance);
@ -337,14 +387,19 @@ handler_find (gpointer instance,
mask = ~mask; mask = ~mask;
for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) 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_CLOSURE) || handler->closure == closure) &&
((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
handler->closure->meta_marshal == 0 && handler->closure->meta_marshal == 0 &&
((GCClosure*) handler->closure)->callback == func))) ((GCClosure*) handler->closure)->callback == func)))
return handler; {
mlist = handler_match_prepend (mlist, handler, signal_id);
if (one_and_only)
return mlist;
}
} }
else else
{ {
@ -369,19 +424,24 @@ handler_find (gpointer instance,
} }
for (handler = hlist->handlers; handler; handler = handler->next) 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_CLOSURE) || handler->closure == closure) &&
((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) &&
((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) &&
((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller &&
handler->closure->meta_marshal == 0 && handler->closure->meta_marshal == 0 &&
((GCClosure*) handler->closure)->callback == func))) ((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* static inline Handler*
@ -433,7 +493,7 @@ handler_unref_R (guint signal_id,
{ {
if (handler->next) if (handler->next)
handler->next->prev = handler->prev; 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; handler->prev->next = handler->next;
else else
{ {
@ -551,6 +611,9 @@ g_signal_init (void) /* sync with gtype.c */
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
if (!g_n_signal_nodes) if (!g_n_signal_nodes)
{ {
/* handler_id_node_prepend() requires this */
g_assert (sizeof (GList) == sizeof (HandlerMatch));
/* setup signal key array */ /* setup signal key array */
g_signal_key_bsa.cmp_func = signal_key_cmp; g_signal_key_bsa.cmp_func = signal_key_cmp;
g_signal_key_bsa.sizeof_node = sizeof (SignalKey); g_signal_key_bsa.sizeof_node = sizeof (SignalKey);
@ -573,7 +636,7 @@ _g_signals_destroy (GType itype)
guint i; guint i;
G_LOCK (g_signal_mutex); 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]; SignalNode *node = g_signal_nodes[i];
@ -1056,7 +1119,7 @@ g_signal_handler_disconnect (gpointer instance,
} }
void void
_g_signal_handlers_destroy (gpointer instance) g_signal_handlers_destroy (gpointer instance)
{ {
GBSearchArray *hlbsa; GBSearchArray *hlbsa;
@ -1107,7 +1170,6 @@ g_signal_handler_find (gpointer instance,
gpointer func, gpointer func,
gpointer data) gpointer data)
{ {
Handler *handler;
guint handler_id = 0; guint handler_id = 0;
g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
@ -1115,9 +1177,15 @@ g_signal_handler_find (gpointer instance,
if (mask & G_SIGNAL_MATCH_MASK) if (mask & G_SIGNAL_MATCH_MASK)
{ {
HandlerMatch *mlist;
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
handler = handler_find (instance, mask, signal_id, detail, closure, func, data); mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE);
handler_id = handler ? handler->id : 0; if (mlist)
{
handler_id = mlist->handler->id;
handler_match_free1_R (mlist, instance);
}
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
} }
@ -1125,28 +1193,27 @@ g_signal_handler_find (gpointer instance,
} }
static guint static guint
signal_handlers_foreach_matched (gpointer instance, signal_handlers_foreach_matched_R (gpointer instance,
GSignalMatchType mask, GSignalMatchType mask,
guint signal_id, guint signal_id,
GQuark detail, GQuark detail,
GClosure *closure, GClosure *closure,
gpointer func, gpointer func,
gpointer data, gpointer data,
void (*callback) (gpointer instance, void (*callback) (gpointer instance,
guint handler_id)) guint handler_id))
{ {
Handler *handler; HandlerMatch *mlist;
guint n_handlers = 0; guint n_handlers = 0;
handler = handler_find (instance, mask, signal_id, detail, closure, func, data); mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE);
while (handler && handler->id) while (mlist)
{ {
n_handlers++; n_handlers++;
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
callback (instance, handler->id); callback (instance, mlist->handler->id);
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
/* need constant relookups due to callback */ mlist = handler_match_free1_R (mlist, instance);
handler = handler_find (instance, mask, signal_id, detail, closure, func, data);
} }
return n_handlers; return n_handlers;
@ -1169,9 +1236,9 @@ g_signal_handlers_block_matched (gpointer instance,
if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
{ {
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail, n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
closure, func, data, closure, func, data,
g_signal_handler_block); g_signal_handler_block);
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
} }
@ -1195,9 +1262,9 @@ g_signal_handlers_unblock_matched (gpointer instance,
if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
{ {
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail, n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
closure, func, data, closure, func, data,
g_signal_handler_unblock); g_signal_handler_unblock);
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
} }
@ -1221,9 +1288,9 @@ g_signal_handlers_disconnect_matched (gpointer instance,
if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA))
{ {
G_LOCK (g_signal_mutex); G_LOCK (g_signal_mutex);
n_handlers = signal_handlers_foreach_matched (instance, mask, signal_id, detail, n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail,
closure, func, data, closure, func, data,
g_signal_handler_disconnect); g_signal_handler_disconnect);
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
} }
@ -1236,7 +1303,8 @@ g_signal_has_handler_pending (gpointer instance,
GQuark detail, GQuark detail,
gboolean may_be_blocked) 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 (G_TYPE_CHECK_INSTANCE (instance), FALSE);
g_return_val_if_fail (signal_id > 0, FALSE); g_return_val_if_fail (signal_id > 0, FALSE);
@ -1253,13 +1321,19 @@ g_signal_has_handler_pending (gpointer instance,
return FALSE; return FALSE;
} }
} }
handler = handler_find (instance, mlist = handlers_find (instance,
(G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)),
(may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), signal_id, detail, NULL, NULL, NULL, TRUE);
signal_id, detail, NULL, NULL, NULL); if (mlist)
{
has_pending = TRUE;
handler_match_free1_R (mlist, instance);
}
else
has_pending = FALSE;
G_UNLOCK (g_signal_mutex); G_UNLOCK (g_signal_mutex);
return handler != NULL; return has_pending;
} }
void void

View File

@ -169,7 +169,7 @@ gboolean g_signal_parse_name (const gchar *detailed_signal,
guint *signal_id_p, guint *signal_id_p,
GQuark *detail_p, GQuark *detail_p,
gboolean force_detail_quark); gboolean force_detail_quark);
void _g_signal_handlers_destroy (gpointer instance); void g_signal_handlers_destroy (gpointer instance);
void _g_signals_destroy (GType itype); void _g_signals_destroy (GType itype);

View File

@ -18,6 +18,7 @@
*/ */
#include "gtype.h" #include "gtype.h"
#include "gtypeplugin.h"
#include <string.h> #include <string.h>
#define FIXME_DISABLE_PREALLOCATIONS #define FIXME_DISABLE_PREALLOCATIONS
@ -45,10 +46,6 @@
G_TYPE_FLAG_DEEP_DERIVABLE) G_TYPE_FLAG_DEEP_DERIVABLE)
#define TYPE_FLAG_MASK (G_TYPE_FLAG_ABSTRACT) #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 --- */ /* --- typedefs --- */
@ -398,31 +395,19 @@ check_plugin (GTypePlugin *plugin,
type_name); type_name);
return FALSE; return FALSE;
} }
if (!plugin->vtable) if (!G_IS_TYPE_PLUGIN (plugin))
{ {
g_warning ("plugin for type `%s' has no function table", g_warning ("plugin pointer (%p) for type `%s' is invalid",
type_name); plugin, type_name);
return FALSE; return FALSE;
} }
if (!plugin->vtable->plugin_ref) if (need_complete_type_info && !G_TYPE_PLUGIN_GET_CLASS (plugin)->complete_type_info)
{
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)
{ {
g_warning ("plugin for type `%s' has no complete_type_info() implementation", g_warning ("plugin for type `%s' has no complete_type_info() implementation",
type_name); type_name);
return FALSE; 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", g_warning ("plugin for type `%s' has no complete_interface_info() implementation",
type_name); type_name);
@ -830,7 +815,7 @@ type_data_ref (TypeNode *node)
memset (&tmp_info, 0, sizeof (tmp_info)); memset (&tmp_info, 0, sizeof (tmp_info));
memset (&tmp_value_table, 0, sizeof (tmp_value_table)); 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); 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); check_type_info (pnode, G_TYPE_FUNDAMENTAL (NODE_TYPE (node)), NODE_NAME (node), &tmp_info);
type_data_make (node, &tmp_info, type_data_make (node, &tmp_info,
@ -930,7 +915,7 @@ type_iface_retrive_holder_info (TypeNode *iface,
type_data_ref (iface); type_data_ref (iface);
memset (&tmp_info, 0, sizeof (tmp_info)); 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); g_type_plugin_complete_interface_info (iholder->plugin, NODE_TYPE (iface), instance_type, &tmp_info);
check_interface_info (iface, instance_type, &tmp_info); check_interface_info (iface, instance_type, &tmp_info);
iholder->info = g_memdup (&tmp_info, sizeof (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); g_free (iholder->info);
iholder->info = NULL; iholder->info = NULL;
g_type_plugin_unref (iholder->plugin); g_type_plugin_unuse (iholder->plugin);
type_data_unref (iface, FALSE); type_data_unref (iface, FALSE);
} }
@ -1279,7 +1264,7 @@ type_data_last_unref (GType type,
if (ptype) if (ptype)
type_data_unref (LOOKUP_TYPE_NODE (ptype), FALSE); 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 */ type_data_make (node, &info, NULL); /* FIXME */
g_assert (type == G_TYPE_INTERFACE); g_assert (type == G_TYPE_INTERFACE);
/* G_TYPE_TYPE_PLUGIN
*/
g_type_plugin_get_type ();
/* G_TYPE_* value types /* G_TYPE_* value types
*/ */
g_value_types_init (); g_value_types_init ();

View File

@ -116,7 +116,6 @@ typedef guint32 GType;
typedef struct _GValue GValue; typedef struct _GValue GValue;
typedef union _GTypeCValue GTypeCValue; typedef union _GTypeCValue GTypeCValue;
typedef struct _GTypePlugin GTypePlugin; typedef struct _GTypePlugin GTypePlugin;
typedef struct _GTypePluginVTable GTypePluginVTable;
typedef struct _GTypeClass GTypeClass; typedef struct _GTypeClass GTypeClass;
typedef struct _GTypeInterface GTypeInterface; typedef struct _GTypeInterface GTypeInterface;
typedef struct _GTypeInstance GTypeInstance; 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(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_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_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_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_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))) #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); gpointer iface_data);
typedef void (*GInterfaceFinalizeFunc) (gpointer g_iface, typedef void (*GInterfaceFinalizeFunc) (gpointer g_iface,
gpointer iface_data); 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, typedef gboolean (*GTypeClassCacheFunc) (gpointer cache_data,
GTypeClass *g_class); 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 >*/ typedef enum /*< skip >*/
{ {
G_TYPE_FLAG_CLASSED = (1 << 0), 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_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_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_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)) #define _G_TYPE_IGI(ip, gt, ct) ((ct*) g_type_interface_peek (((GTypeInstance*) ip)->g_class, gt))

100
gobject/gtypeplugin.c Normal file
View File

@ -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);
}

85
gobject/gtypeplugin.h Normal file
View File

@ -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 <gobject/gtype.h>
#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__ */