mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-14 19:55:12 +01:00
fix post class_init interface initialization logic for child types.
Thu Oct 2 07:37:12 2003 Tim Janik <timj@gtk.org> * gtype.c: fix post class_init interface initialization logic for child types.
This commit is contained in:
parent
3e61c90b59
commit
96a7e24043
@ -1,3 +1,8 @@
|
|||||||
|
Thu Oct 2 07:37:12 2003 Tim Janik <timj@gtk.org>
|
||||||
|
|
||||||
|
* gtype.c: fix post class_init interface initialization logic
|
||||||
|
for child types.
|
||||||
|
|
||||||
Thu Oct 2 01:16:50 2003 Owen Taylor <otaylor@redhat.com>
|
Thu Oct 2 01:16:50 2003 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* gtype.[ch]: Add g_type_add/remove_interface_check(),
|
* gtype.[ch]: Add g_type_add/remove_interface_check(),
|
||||||
|
126
gobject/gtype.c
126
gobject/gtype.c
@ -151,6 +151,10 @@ static inline void type_set_qdata_W (TypeNode *node,
|
|||||||
gpointer data);
|
gpointer data);
|
||||||
static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface,
|
static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface,
|
||||||
GType instance_type);
|
GType instance_type);
|
||||||
|
static gboolean type_iface_vtable_base_init_Wm (TypeNode *iface,
|
||||||
|
TypeNode *node);
|
||||||
|
static void type_iface_vtable_iface_init_Wm (TypeNode *iface,
|
||||||
|
TypeNode *node);
|
||||||
static gboolean type_node_is_a_L (TypeNode *node,
|
static gboolean type_node_is_a_L (TypeNode *node,
|
||||||
TypeNode *iface_node);
|
TypeNode *iface_node);
|
||||||
|
|
||||||
@ -1104,8 +1108,9 @@ type_data_unref_Wm (TypeNode *node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
type_node_add_iface_entry_W (TypeNode *node,
|
type_node_add_iface_entry_W (TypeNode *node,
|
||||||
GType iface_type)
|
GType iface_type,
|
||||||
|
IFaceEntry *parent_entry)
|
||||||
{
|
{
|
||||||
IFaceEntry *entries;
|
IFaceEntry *entries;
|
||||||
guint i;
|
guint i;
|
||||||
@ -1116,13 +1121,23 @@ type_node_add_iface_entry_W (TypeNode *node,
|
|||||||
for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
|
for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
|
||||||
if (entries[i].iface_type == iface_type)
|
if (entries[i].iface_type == iface_type)
|
||||||
{
|
{
|
||||||
/* this can (should) only happen if our parent type already conformed
|
/* this can happen in two cases:
|
||||||
* to iface_type and node got it's own holder info. here, our
|
* - our parent type already conformed to iface_type and node
|
||||||
* children should already have entries with NULL vtables, so
|
* got it's own holder info. here, our children already have
|
||||||
* we're actually done.
|
* entries and NULL vtables, since this will only work for
|
||||||
|
* uninitialized classes.
|
||||||
|
* - an interface type is added to an ancestor after it was
|
||||||
|
* added to a child type.
|
||||||
*/
|
*/
|
||||||
g_assert (entries[i].vtable == NULL);
|
if (!parent_entry)
|
||||||
return;
|
g_assert (entries[i].vtable == NULL && entries[i].init_state == UNINITIALIZED);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* sick, interface is added to ancestor *after* child type;
|
||||||
|
* nothing todo, the entry and our children were already setup correctly
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (entries[i].iface_type > iface_type)
|
else if (entries[i].iface_type > iface_type)
|
||||||
break;
|
break;
|
||||||
@ -1135,22 +1150,29 @@ type_node_add_iface_entry_W (TypeNode *node,
|
|||||||
entries[i].iface_type = iface_type;
|
entries[i].iface_type = iface_type;
|
||||||
entries[i].vtable = NULL;
|
entries[i].vtable = NULL;
|
||||||
entries[i].init_state = UNINITIALIZED;
|
entries[i].init_state = UNINITIALIZED;
|
||||||
|
|
||||||
for (i = 0; i < node->n_children; i++)
|
if (parent_entry)
|
||||||
type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type);
|
{
|
||||||
|
if (node->data && node->data->class.init_state >= BASE_IFACE_INIT)
|
||||||
|
{
|
||||||
|
entries[i].init_state = INITIALIZED;
|
||||||
|
entries[i].vtable = parent_entry->vtable;
|
||||||
|
}
|
||||||
|
for (i = 0; i < node->n_children; i++)
|
||||||
|
type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), iface_type, &entries[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
type_add_interface_W (TypeNode *node,
|
type_add_interface_Wm (TypeNode *node,
|
||||||
TypeNode *iface,
|
TypeNode *iface,
|
||||||
const GInterfaceInfo *info,
|
const GInterfaceInfo *info,
|
||||||
GTypePlugin *plugin)
|
GTypePlugin *plugin)
|
||||||
{
|
{
|
||||||
IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
|
IFaceHolder *iholder = g_new0 (IFaceHolder, 1);
|
||||||
|
IFaceEntry *entry;
|
||||||
|
guint i;
|
||||||
|
|
||||||
/* we must not call any functions of GInterfaceInfo from within here, since
|
|
||||||
* we got most probably called from _within_ a type registration function
|
|
||||||
*/
|
|
||||||
g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
|
g_assert (node->is_instantiatable && NODE_IS_IFACE (iface) && ((info && !plugin) || (!info && plugin)));
|
||||||
|
|
||||||
iholder->next = iface_node_get_holders_L (iface);
|
iholder->next = iface_node_get_holders_L (iface);
|
||||||
@ -1158,8 +1180,28 @@ type_add_interface_W (TypeNode *node,
|
|||||||
iholder->instance_type = NODE_TYPE (node);
|
iholder->instance_type = NODE_TYPE (node);
|
||||||
iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
|
iholder->info = info ? g_memdup (info, sizeof (*info)) : NULL;
|
||||||
iholder->plugin = plugin;
|
iholder->plugin = plugin;
|
||||||
|
|
||||||
|
/* create an iface entry for this type */
|
||||||
|
type_node_add_iface_entry_W (node, NODE_TYPE (iface), NULL);
|
||||||
|
|
||||||
type_node_add_iface_entry_W (node, NODE_TYPE (iface));
|
/* if the class is already (partly) initialized, we may need to base
|
||||||
|
* initalize and/or initialize the new interface.
|
||||||
|
*/
|
||||||
|
if (node->data)
|
||||||
|
{
|
||||||
|
InitState class_state = node->data->class.init_state;
|
||||||
|
|
||||||
|
if (class_state >= BASE_IFACE_INIT)
|
||||||
|
type_iface_vtable_base_init_Wm (iface, node);
|
||||||
|
|
||||||
|
if (class_state >= IFACE_INIT)
|
||||||
|
type_iface_vtable_iface_init_Wm (iface, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create iface entries for children of this type */
|
||||||
|
entry = type_lookup_iface_entry_L (node, iface);
|
||||||
|
for (i = 0; i < node->n_children; i++)
|
||||||
|
type_node_add_iface_entry_W (lookup_type_node_I (node->children[i]), NODE_TYPE (iface), entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1675,6 +1717,9 @@ type_iface_vtable_base_init_Wm (TypeNode *iface,
|
|||||||
|
|
||||||
/* Finishes what type_iface_vtable_base_init_Wm started by
|
/* Finishes what type_iface_vtable_base_init_Wm started by
|
||||||
* calling the interface init function.
|
* calling the interface init function.
|
||||||
|
* this function may only be called for types with their
|
||||||
|
* own interface holder info, i.e. types for which
|
||||||
|
* g_type_add_interface*() was called and not children thereof.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
type_iface_vtable_iface_init_Wm (TypeNode *iface,
|
type_iface_vtable_iface_init_Wm (TypeNode *iface,
|
||||||
@ -1687,6 +1732,7 @@ type_iface_vtable_iface_init_Wm (TypeNode *iface,
|
|||||||
|
|
||||||
/* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
|
/* iholder->info should have been filled in by type_iface_vtable_base_init_Wm() */
|
||||||
g_assert (iface->data && entry && iholder && iholder->info);
|
g_assert (iface->data && entry && iholder && iholder->info);
|
||||||
|
g_assert (entry->init_state == IFACE_INIT); /* assert prior base_init() */
|
||||||
|
|
||||||
entry->init_state = INITIALIZED;
|
entry->init_state = INITIALIZED;
|
||||||
|
|
||||||
@ -1861,10 +1907,14 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
node->data->class.class_init (class, (gpointer) node->data->class.class_data);
|
node->data->class.class_init (class, (gpointer) node->data->class.class_data);
|
||||||
|
|
||||||
G_WRITE_LOCK (&type_rw_lock);
|
G_WRITE_LOCK (&type_rw_lock);
|
||||||
|
|
||||||
node->data->class.init_state = IFACE_INIT;
|
node->data->class.init_state = IFACE_INIT;
|
||||||
|
|
||||||
/* finish initialize the interfaces through our holder info
|
/* finish initializing the interfaces through our holder info.
|
||||||
|
* inherited interfaces are already init_state == INITIALIZED, because
|
||||||
|
* they either got setup in the above base_init loop, or during
|
||||||
|
* class_init from within type_add_interface_Wm() for this or
|
||||||
|
* an anchestor type.
|
||||||
*/
|
*/
|
||||||
i = 0;
|
i = 0;
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
@ -1892,26 +1942,6 @@ type_class_init_Wm (TypeNode *node,
|
|||||||
node->data->class.init_state = INITIALIZED;
|
node->data->class.init_state = INITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function is called when we add a new interface to an existing type;
|
|
||||||
* depending on whether the type already has a class or not, we call
|
|
||||||
* base-init and interface-init functions. If we are called *while* the
|
|
||||||
* class is being initialized, then we need to update an array saying which
|
|
||||||
* interfaces for the class have been initialized.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
type_iface_vtable_init_Wm (TypeNode *node,
|
|
||||||
TypeNode *iface)
|
|
||||||
{
|
|
||||||
InitState class_state =
|
|
||||||
node->data ? node->data->class.init_state : UNINITIALIZED;
|
|
||||||
|
|
||||||
if (class_state >= BASE_IFACE_INIT)
|
|
||||||
type_iface_vtable_base_init_Wm (iface, node);
|
|
||||||
|
|
||||||
if (class_state >= IFACE_INIT)
|
|
||||||
type_iface_vtable_iface_init_Wm (iface, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
type_data_finalize_class_ifaces_Wm (TypeNode *node)
|
type_data_finalize_class_ifaces_Wm (TypeNode *node)
|
||||||
{
|
{
|
||||||
@ -2295,13 +2325,7 @@ g_type_add_interface_static (GType instance_type,
|
|||||||
TypeNode *iface = lookup_type_node_I (interface_type);
|
TypeNode *iface = lookup_type_node_I (interface_type);
|
||||||
|
|
||||||
if (check_interface_info_I (iface, NODE_TYPE (node), info))
|
if (check_interface_info_I (iface, NODE_TYPE (node), info))
|
||||||
{
|
type_add_interface_Wm (node, iface, info, NULL);
|
||||||
type_add_interface_W (node, iface, info, NULL);
|
|
||||||
/* If we have a class already, we may need to base initalize
|
|
||||||
* and/or initialize the new interface.
|
|
||||||
*/
|
|
||||||
type_iface_vtable_init_Wm (node, iface);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
G_WRITE_UNLOCK (&type_rw_lock);
|
G_WRITE_UNLOCK (&type_rw_lock);
|
||||||
}
|
}
|
||||||
@ -2326,11 +2350,7 @@ g_type_add_interface_dynamic (GType instance_type,
|
|||||||
{
|
{
|
||||||
TypeNode *iface = lookup_type_node_I (interface_type);
|
TypeNode *iface = lookup_type_node_I (interface_type);
|
||||||
|
|
||||||
type_add_interface_W (node, iface, NULL, plugin);
|
type_add_interface_Wm (node, iface, NULL, plugin);
|
||||||
/* If we have a class already, we may need to base initalize
|
|
||||||
* and/or initialize the new interface.
|
|
||||||
*/
|
|
||||||
type_iface_vtable_init_Wm (node, iface);
|
|
||||||
}
|
}
|
||||||
G_WRITE_UNLOCK (&type_rw_lock);
|
G_WRITE_UNLOCK (&type_rw_lock);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user