summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2023-02-04 16:41:55 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2023-02-04 16:41:55 +0100
commitd5136854e9b363927d61a32deeead7d761dd24c2 (patch)
treefbcd02ec23a2ce61dae3db09535e086b1da17212
parent35170735dedc7e2cc48c846261204fd5e0d99fb5 (diff)
downloadglib-ebassi/gtype-refcount.tar.gz
Drop TypeNode reference countingebassi/gtype-refcount
We don't allow unloading types, both static and dynamic, since 2013. The code that deals with reference counting is mostly dead code, and makes reasoning about the type system more complicated than necessary. Since type classes and interfaces can only be instantiated, we introduce explicit getter functions that create a GTypeClass or a GTypeInterface vtable; the ref() and unref() API gets a "soft" deprecation, to allow people to progressively port their code.
-rw-r--r--gobject/gtype.c476
-rw-r--r--gobject/gtype.h4
2 files changed, 128 insertions, 352 deletions
diff --git a/gobject/gtype.c b/gobject/gtype.c
index 8665db294..ac6a7e96f 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -191,10 +191,6 @@ static void type_data_make_W (TypeNode *node,
const GTypeInfo *info,
const GTypeValueTable *value_table);
static inline void type_data_ref_Wm (TypeNode *node);
-static inline void type_data_unref_U (TypeNode *node,
- gboolean uncached);
-static void type_data_last_unref_Wm (TypeNode * node,
- gboolean uncached);
static inline gpointer type_get_qdata_L (TypeNode *node,
GQuark quark);
static inline void type_set_qdata_W (TypeNode *node,
@@ -230,7 +226,6 @@ typedef enum
/* --- structures --- */
struct _TypeNode
{
- guint ref_count; /* (atomic) */
#ifdef G_ENABLE_DEBUG
guint instance_count; /* (atomic) */
#endif
@@ -264,7 +259,6 @@ struct _TypeNode
#define NODE_PARENT_TYPE(node) (node->supers[1])
#define NODE_FUNDAMENTAL_TYPE(node) (node->supers[node->n_supers])
#define NODE_NAME(node) (g_quark_to_string (node->qname))
-#define NODE_REFCOUNT(node) ((guint) g_atomic_int_get ((int *) &(node)->ref_count))
#define NODE_IS_BOXED(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_BOXED)
#define NODE_IS_IFACE(node) (NODE_FUNDAMENTAL_TYPE (node) == G_TYPE_INTERFACE)
#define CLASSED_NODE_IFACES_ENTRIES(node) (&(node)->_prot.iface_entries)
@@ -1237,8 +1231,6 @@ type_data_make_W (TypeNode *node,
GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
g_assert (node->data->common.value_table != NULL); /* paranoid */
-
- g_atomic_int_set ((int *) &node->ref_count, 1);
}
static inline void
@@ -1274,25 +1266,13 @@ type_data_ref_Wm (TypeNode *node)
check_value_table_I (NODE_NAME (node),
&tmp_value_table) ? &tmp_value_table : NULL);
}
- else
- {
- g_assert (NODE_REFCOUNT (node) > 0);
-
- g_atomic_int_inc ((int *) &node->ref_count);
- }
}
static inline gboolean
type_data_ref_U (TypeNode *node)
{
- guint current;
-
- do {
- current = NODE_REFCOUNT (node);
-
- if (current < 1)
- return FALSE;
- } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current + 1));
+ if (node->data == NULL)
+ return FALSE;
return TRUE;
}
@@ -1811,29 +1791,6 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface,
}
static void
-type_iface_blow_holder_info_Wm (TypeNode *iface,
- GType instance_type)
-{
- IFaceHolder *iholder = iface_node_get_holders_L (iface);
-
- g_assert (NODE_IS_IFACE (iface));
-
- while (iholder->instance_type != instance_type)
- iholder = iholder->next;
-
- if (iholder->info && iholder->plugin)
- {
- g_free (iholder->info);
- iholder->info = NULL;
-
- G_WRITE_UNLOCK (&type_rw_lock);
- g_type_plugin_unuse (iholder->plugin);
- type_data_unref_U (iface, FALSE);
- G_WRITE_LOCK (&type_rw_lock);
- }
-}
-
-static void
maybe_issue_deprecation_warning (GType type)
{
static GHashTable *already_warned_table;
@@ -2205,41 +2162,6 @@ type_iface_vtable_iface_init_Wm (TypeNode *iface,
}
}
-static gboolean
-type_iface_vtable_finalize_Wm (TypeNode *iface,
- TypeNode *node,
- GTypeInterface *vtable)
-{
- IFaceEntry *entry = type_lookup_iface_entry_L (node, iface);
- IFaceHolder *iholder;
-
- /* type_iface_retrieve_holder_info_Wm() doesn't modify write lock for returning NULL */
- iholder = type_iface_retrieve_holder_info_Wm (iface, NODE_TYPE (node), FALSE);
- if (!iholder)
- return FALSE; /* we don't modify write lock upon FALSE */
-
- g_assert (entry && entry->vtable == vtable && iholder->info);
-
- entry->vtable = NULL;
- entry->init_state = UNINITIALIZED;
- if (iholder->info->interface_finalize || iface->data->iface.vtable_finalize_base)
- {
- G_WRITE_UNLOCK (&type_rw_lock);
- if (iholder->info->interface_finalize)
- iholder->info->interface_finalize (vtable, iholder->info->interface_data);
- if (iface->data->iface.vtable_finalize_base)
- iface->data->iface.vtable_finalize_base (vtable);
- G_WRITE_LOCK (&type_rw_lock);
- }
- vtable->g_type = 0;
- vtable->g_instance_type = 0;
- g_free (vtable);
-
- type_iface_blow_holder_info_Wm (iface, NODE_TYPE (node));
-
- return TRUE; /* write lock modified */
-}
-
static void
type_class_init_Wm (TypeNode *node,
GTypeClass *pclass)
@@ -2400,193 +2322,6 @@ type_class_init_Wm (TypeNode *node,
g_atomic_int_set (&node->data->class.init_state, INITIALIZED);
}
-static void
-type_data_finalize_class_ifaces_Wm (TypeNode *node)
-{
- guint i;
- IFaceEntries *entries;
-
- g_assert (node->is_instantiatable && node->data && node->data->class.class && NODE_REFCOUNT (node) == 0);
-
- reiterate:
- entries = CLASSED_NODE_IFACES_ENTRIES_LOCKED (node);
- for (i = 0; entries != NULL && i < IFACE_ENTRIES_N_ENTRIES (entries); i++)
- {
- IFaceEntry *entry = &entries->entry[i];
- if (entry->vtable)
- {
- if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
- {
- /* refetch entries, IFACES_ENTRIES might be modified */
- goto reiterate;
- }
- else
- {
- /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
- * iface vtable came from parent
- */
- entry->vtable = NULL;
- entry->init_state = UNINITIALIZED;
- }
- }
- }
-}
-
-static void
-type_data_finalize_class_U (TypeNode *node,
- ClassData *cdata)
-{
- GTypeClass *class = cdata->class;
- TypeNode *bnode;
-
- g_assert (cdata->class && NODE_REFCOUNT (node) == 0);
-
- if (cdata->class_finalize)
- cdata->class_finalize (class, (gpointer) cdata->class_data);
-
- /* call all base class destruction functions in descending order
- */
- if (cdata->class_finalize_base)
- cdata->class_finalize_base (class);
- for (bnode = lookup_type_node_I (NODE_PARENT_TYPE (node)); bnode; bnode = lookup_type_node_I (NODE_PARENT_TYPE (bnode)))
- if (bnode->data->class.class_finalize_base)
- bnode->data->class.class_finalize_base (class);
-
- g_free (cdata->class);
-}
-
-static void
-type_data_last_unref_Wm (TypeNode *node,
- gboolean uncached)
-{
- g_return_if_fail (node != NULL && node->plugin != NULL);
-
- if (!node->data || NODE_REFCOUNT (node) == 0)
- {
- g_critical ("cannot drop last reference to unreferenced type '%s'",
- NODE_NAME (node));
- return;
- }
-
- /* call class cache hooks */
- if (node->is_classed && node->data && node->data->class.class && static_n_class_cache_funcs && !uncached)
- {
- guint i;
-
- G_WRITE_UNLOCK (&type_rw_lock);
- G_READ_LOCK (&type_rw_lock);
- for (i = 0; i < static_n_class_cache_funcs; i++)
- {
- GTypeClassCacheFunc cache_func = static_class_cache_funcs[i].cache_func;
- gpointer cache_data = static_class_cache_funcs[i].cache_data;
- gboolean need_break;
-
- G_READ_UNLOCK (&type_rw_lock);
- need_break = cache_func (cache_data, node->data->class.class);
- G_READ_LOCK (&type_rw_lock);
- if (!node->data || NODE_REFCOUNT (node) == 0)
- INVALID_RECURSION ("GType class cache function ", cache_func, NODE_NAME (node));
- if (need_break)
- break;
- }
- G_READ_UNLOCK (&type_rw_lock);
- G_WRITE_LOCK (&type_rw_lock);
- }
-
- /* may have been re-referenced meanwhile */
- if (g_atomic_int_dec_and_test ((int *) &node->ref_count))
- {
- GType ptype = NODE_PARENT_TYPE (node);
- TypeData *tdata;
-
- if (node->is_instantiatable)
- {
- /* destroy node->data->instance.mem_chunk */
- }
-
- tdata = node->data;
- if (node->is_classed && tdata->class.class)
- {
- if (CLASSED_NODE_IFACES_ENTRIES_LOCKED (node) != NULL)
- type_data_finalize_class_ifaces_Wm (node);
- node->mutatable_check_cache = FALSE;
- node->data = NULL;
- G_WRITE_UNLOCK (&type_rw_lock);
- type_data_finalize_class_U (node, &tdata->class);
- G_WRITE_LOCK (&type_rw_lock);
- }
- else if (NODE_IS_IFACE (node) && tdata->iface.dflt_vtable)
- {
- node->mutatable_check_cache = FALSE;
- node->data = NULL;
- if (tdata->iface.dflt_finalize || tdata->iface.vtable_finalize_base)
- {
- G_WRITE_UNLOCK (&type_rw_lock);
- if (tdata->iface.dflt_finalize)
- tdata->iface.dflt_finalize (tdata->iface.dflt_vtable, (gpointer) tdata->iface.dflt_data);
- if (tdata->iface.vtable_finalize_base)
- tdata->iface.vtable_finalize_base (tdata->iface.dflt_vtable);
- G_WRITE_LOCK (&type_rw_lock);
- }
- g_free (tdata->iface.dflt_vtable);
- }
- else
- {
- node->mutatable_check_cache = FALSE;
- node->data = NULL;
- }
-
- /* freeing tdata->common.value_table and its contents is taken care of
- * by allocating it in one chunk with tdata
- */
- g_free (tdata);
-
- G_WRITE_UNLOCK (&type_rw_lock);
- g_type_plugin_unuse (node->plugin);
- if (ptype)
- type_data_unref_U (lookup_type_node_I (ptype), FALSE);
- G_WRITE_LOCK (&type_rw_lock);
- }
-}
-
-static inline void
-type_data_unref_U (TypeNode *node,
- gboolean uncached)
-{
- guint current;
-
- do {
- current = NODE_REFCOUNT (node);
-
- if (current <= 1)
- {
- if (!node->plugin)
- {
- g_critical ("static type '%s' unreferenced too often",
- NODE_NAME (node));
- return;
- }
- else
- {
- /* This is the last reference of a type from a plugin. We are
- * experimentally disabling support for unloading type
- * plugins, so don't allow the last ref to drop.
- */
- return;
- }
-
- g_assert (current > 0);
-
- g_rec_mutex_lock (&class_init_rec_mutex); /* required locking order: 1) class_init_rec_mutex, 2) type_rw_lock */
- G_WRITE_LOCK (&type_rw_lock);
- type_data_last_unref_Wm (node, uncached);
- G_WRITE_UNLOCK (&type_rw_lock);
- g_rec_mutex_unlock (&class_init_rec_mutex);
- return;
- }
- } while (!g_atomic_int_compare_and_exchange ((int *) &node->ref_count, current, current - 1));
-}
-
/**
* g_type_add_class_cache_func: (skip)
* @cache_data: data to be passed to @cache_func
@@ -3023,19 +2758,25 @@ g_type_add_interface_dynamic (GType instance_type,
/* --- public API functions --- */
+
/**
- * g_type_class_ref:
+ * g_type_class_get:
* @type: type ID of a classed type
*
- * Increments the reference count of the class structure belonging to
- * @type. This function will demand-create the class if it doesn't
- * exist already.
+ * Retrieves the type class of the given @type.
*
- * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
- * structure for the given type ID
+ * This function will create the class on demand if it does not exist
+ * already.
+ *
+ * If you don't want to create the class, use g_type_class_peek() instead.
+ *
+ * Returns: (transfer none) (type GObject.TypeClass): the class structure
+ * for the type
+ *
+ * Since: FIXME
*/
gpointer
-g_type_class_ref (GType type)
+g_type_class_get (GType type)
{
TypeNode *node;
GType ptype;
@@ -3069,7 +2810,7 @@ g_type_class_ref (GType type)
/* we need an initialized parent class for initializing derived classes */
ptype = NODE_PARENT_TYPE (node);
- pclass = ptype ? g_type_class_ref (ptype) : NULL;
+ pclass = ptype ? g_type_class_get (ptype) : NULL;
G_WRITE_LOCK (&type_rw_lock);
@@ -3090,28 +2831,40 @@ g_type_class_ref (GType type)
}
/**
+ * g_type_class_ref:
+ * @type: type ID of a classed type
+ *
+ * Increments the reference count of the class structure belonging to
+ * @type.
+ *
+ * This function will demand-create the class if it doesn't exist already.
+ *
+ * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
+ * structure for the given type ID
+ *
+ * Deprecated: FIXME: Use g_type_class_get() instead
+ */
+gpointer
+g_type_class_ref (GType type)
+{
+ return g_type_class_get (type);
+}
+
+/**
* g_type_class_unref:
* @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
*
* Decrements the reference count of the class structure being passed in.
+ *
* Once the last reference count of a class has been released, classes
* may be finalized by the type system, so further dereferencing of a
* class pointer after g_type_class_unref() are invalid.
+ *
+ * Deprecated: FIXME: This function does not do anything.
*/
void
g_type_class_unref (gpointer g_class)
{
- TypeNode *node;
- GTypeClass *class = g_class;
-
- g_return_if_fail (g_class != NULL);
-
- node = lookup_type_node_I (class->g_type);
- if (node && node->is_classed && NODE_REFCOUNT (node))
- type_data_unref_U (node, FALSE);
- else
- g_critical ("cannot unreference class of invalid (unclassed) type '%s'",
- type_descriptive_name_I (class->g_type));
}
/**
@@ -3119,39 +2872,35 @@ g_type_class_unref (gpointer g_class)
* @g_class: (type GObject.TypeClass): a #GTypeClass structure to unref
*
* A variant of g_type_class_unref() for use in #GTypeClassCacheFunc
- * implementations. It unreferences a class without consulting the chain
+ * implementations.
+ *
+ * It unreferences a class without consulting the chain
* of #GTypeClassCacheFuncs, avoiding the recursion which would occur
* otherwise.
+ *
+ * Deprecated: FIXME: This function does not do anything
*/
void
g_type_class_unref_uncached (gpointer g_class)
{
- TypeNode *node;
- GTypeClass *class = g_class;
-
- g_return_if_fail (g_class != NULL);
-
- node = lookup_type_node_I (class->g_type);
- if (node && node->is_classed && NODE_REFCOUNT (node))
- type_data_unref_U (node, TRUE);
- else
- g_critical ("cannot unreference class of invalid (unclassed) type '%s'",
- type_descriptive_name_I (class->g_type));
}
/**
* g_type_class_peek:
* @type: type ID of a classed type
*
+ * Retrieves the class for a give type.
+ *
* This function is essentially the same as g_type_class_ref(),
- * except that the classes reference count isn't incremented.
+ * except that the class may have not been instantiated yet.
+ *
* As a consequence, this function may return %NULL if the class
* of the type passed in does not currently exist (hasn't been
* referenced before).
*
* Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
- * structure for the given type ID or %NULL if the class does not
- * currently exist
+ * structure for the given type ID or %NULL if the class does not
+ * currently exist
*/
gpointer
g_type_class_peek (GType type)
@@ -3160,9 +2909,9 @@ g_type_class_peek (GType type)
gpointer class;
node = lookup_type_node_I (type);
- if (node && node->is_classed && NODE_REFCOUNT (node) &&
+ if (node && node->is_classed &&
+ node->data &&
g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
- /* ref_count _may_ be 0 */
class = node->data->class.class;
else
class = NULL;
@@ -3177,9 +2926,9 @@ g_type_class_peek (GType type)
* A more efficient version of g_type_class_peek() which works only for
* static types.
*
- * Returns: (type GObject.TypeClass) (transfer none): the #GTypeClass
- * structure for the given type ID or %NULL if the class does not
- * currently exist or is dynamically loaded
+ * Returns: (type GObject.TypeClass) (transfer none) (nullable): the
+ * #GTypeClass structure for the given type ID or %NULL if the class
+ * does not currently exist or is dynamically loaded
*
* Since: 2.4
*/
@@ -3190,10 +2939,9 @@ g_type_class_peek_static (GType type)
gpointer class;
node = lookup_type_node_I (type);
- if (node && node->is_classed && NODE_REFCOUNT (node) &&
+ if (node && node->is_classed && node->data &&
/* peek only static types: */ node->plugin == NULL &&
g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)
- /* ref_count _may_ be 0 */
class = node->data->class.class;
else
class = NULL;
@@ -3204,19 +2952,21 @@ g_type_class_peek_static (GType type)
/**
* g_type_class_peek_parent:
* @g_class: (type GObject.TypeClass): the #GTypeClass structure to
- * retrieve the parent class for
+ * retrieve the parent class for
+ *
+ * Retrieves the class structure of the immediate parent type of the
+ * class passed in.
*
* This is a convenience function often needed in class initializers.
- * It returns the class structure of the immediate parent type of the
- * class passed in. Since derived classes hold a reference count on
- * their parent classes as long as they are instantiated, the returned
- * class will always exist.
+ *
+ * Since derived classes hold a reference on their parent classes as
+ * long as they are instantiated, the returned class will always exist.
*
* This function is essentially equivalent to:
* g_type_class_peek (g_type_parent (G_TYPE_FROM_CLASS (g_class)))
*
* Returns: (type GObject.TypeClass) (transfer none): the parent class
- * of @g_class
+ * of @g_class
*/
gpointer
g_type_class_peek_parent (gpointer g_class)
@@ -3253,9 +3003,9 @@ g_type_class_peek_parent (gpointer g_class)
* Returns the #GTypeInterface structure of an interface to which the
* passed in class conforms.
*
- * Returns: (type GObject.TypeInterface) (transfer none): the #GTypeInterface
- * structure of @iface_type if implemented by @instance_class, %NULL
- * otherwise
+ * Returns: (type GObject.TypeInterface) (transfer none) (nullable): the #GTypeInterface
+ * structure of @iface_type if implemented by @instance_class, %NULL
+ * otherwise
*/
gpointer
g_type_interface_peek (gpointer instance_class,
@@ -3283,14 +3033,15 @@ g_type_interface_peek (gpointer instance_class,
* @g_iface: (type GObject.TypeInterface): a #GTypeInterface structure
*
* Returns the corresponding #GTypeInterface structure of the parent type
- * of the instance type to which @g_iface belongs. This is useful when
- * deriving the implementation of an interface from the parent type and
- * then possibly overriding some methods.
- *
- * Returns: (transfer none) (type GObject.TypeInterface): the
- * corresponding #GTypeInterface structure of the parent type of the
- * instance type to which @g_iface belongs, or %NULL if the parent
- * type doesn't conform to the interface
+ * of the instance type to which @g_iface belongs.
+ *
+ * This is useful when deriving the implementation of an interface from the
+ * parent type and then possibly overriding some methods.
+ *
+ * Returns: (transfer none) (type GObject.TypeInterface) (nullable): the
+ * corresponding #GTypeInterface structure of the parent type of the
+ * instance type to which @g_iface belongs, or %NULL if the parent
+ * type doesn't conform to the interface
*/
gpointer
g_type_interface_peek_parent (gpointer g_iface)
@@ -3331,21 +3082,52 @@ g_type_interface_peek_parent (gpointer g_iface)
*
* Since: 2.4
*
+ * Deprecated: FIXME: Use g_type_default_interface_get() instead
+ *
* Returns: (type GObject.TypeInterface) (transfer none): the default
- * vtable for the interface; call g_type_default_interface_unref()
- * when you are done using the interface.
+ * vtable for the interface; call g_type_default_interface_unref()
+ * when you are done using the interface.
*/
gpointer
g_type_default_interface_ref (GType g_type)
{
+ return g_type_default_interface_get (g_type);
+}
+
+/**
+ * g_type_default_interface_get:
+ * @g_type: an interface type
+ *
+ * Returns the default interface vtable for the given @g_type.
+ *
+ * If the type is not currently in use, then the default vtable
+ * for the type will be created and initialized by calling
+ * the base interface init and default vtable init functions for
+ * the type (the @base_init and @class_init members of #GTypeInfo).
+ *
+ * If you don't want to create the interface vtable, you should use
+ * g_type_default_interface_peek() instead.
+ *
+ * Calling g_type_default_interface_get() is useful when you
+ * want to make sure that signals and properties for an interface
+ * have been installed.
+ *
+ * Returns: (type GObject.TypeInterface) (transfer none): the default
+ * vtable for the interface; call g_type_default_interface_unref()
+ * when you are done using the interface.
+ *
+ * Since: FIXME
+ */
+gpointer
+g_type_default_interface_get (GType g_type)
+{
TypeNode *node;
gpointer dflt_vtable;
G_WRITE_LOCK (&type_rw_lock);
node = lookup_type_node_I (g_type);
- if (!node || !NODE_IS_IFACE (node) ||
- (node->data && NODE_REFCOUNT (node) == 0))
+ if (!node || !NODE_IS_IFACE (node))
{
G_WRITE_UNLOCK (&type_rw_lock);
g_critical ("cannot retrieve default vtable for invalid or non-interface type '%s'",
@@ -3363,8 +3145,6 @@ g_type_default_interface_ref (GType g_type)
type_iface_ensure_dflt_vtable_Wm (node);
g_rec_mutex_unlock (&class_init_rec_mutex);
}
- else
- type_data_ref_Wm (node); /* ref_count >= 1 already */
dflt_vtable = node->data->iface.dflt_vtable;
G_WRITE_UNLOCK (&type_rw_lock);
@@ -3382,8 +3162,8 @@ g_type_default_interface_ref (GType g_type)
* Since: 2.4
*
* Returns: (type GObject.TypeInterface) (transfer none): the default
- * vtable for the interface, or %NULL if the type is not currently
- * in use
+ * vtable for the interface, or %NULL if the type is not currently
+ * in use
*/
gpointer
g_type_default_interface_peek (GType g_type)
@@ -3392,7 +3172,7 @@ g_type_default_interface_peek (GType g_type)
gpointer vtable;
node = lookup_type_node_I (g_type);
- if (node && NODE_IS_IFACE (node) && NODE_REFCOUNT (node))
+ if (node && NODE_IS_IFACE (node) && node->data)
vtable = node->data->iface.dflt_vtable;
else
vtable = NULL;
@@ -3412,21 +3192,12 @@ g_type_default_interface_peek (GType g_type)
* vtable (the @class_finalize member of #GTypeInfo) will be called.
*
* Since: 2.4
+ *
+ * Deprecated: FIXME: This function does not do anything
*/
void
g_type_default_interface_unref (gpointer g_iface)
{
- TypeNode *node;
- GTypeInterface *vtable = g_iface;
-
- g_return_if_fail (g_iface != NULL);
-
- node = lookup_type_node_I (vtable->g_type);
- if (node && NODE_IS_IFACE (node))
- type_data_unref_U (node, FALSE);
- else
- g_critical ("cannot unreference invalid interface default vtable for '%s'",
- type_descriptive_name_I (vtable->g_type));
}
/**
@@ -4315,7 +4086,7 @@ type_check_is_value_type_U (GType type)
restart_check:
if (node)
{
- if (node->data && NODE_REFCOUNT (node) > 0 &&
+ if (node->data &&
node->data->common.value_table->value_init)
tflags = GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags));
else if (NODE_IS_IFACE (node))
@@ -4370,23 +4141,24 @@ g_type_check_value_holds (const GValue *value,
* that implements or has internal knowledge of the implementation of
* @type.
*
- * Returns: location of the #GTypeValueTable associated with @type or
- * %NULL if there is no #GTypeValueTable associated with @type
+ * Returns: (nullable) (transfer none): location of the #GTypeValueTable
+ * associated with @type or %NULL if there is no #GTypeValueTable
+ * associated with @type
*/
-GTypeValueTable*
+GTypeValueTable *
g_type_value_table_peek (GType type)
{
GTypeValueTable *vtable = NULL;
TypeNode *node = lookup_type_node_I (type);
gboolean has_refed_data, has_table;
- if (node && NODE_REFCOUNT (node) && node->mutatable_check_cache)
+ if (node && node->mutatable_check_cache)
return node->data->common.value_table;
G_READ_LOCK (&type_rw_lock);
restart_table_peek:
- has_refed_data = node && node->data && NODE_REFCOUNT (node) > 0;
+ has_refed_data = node && node->data;
has_table = has_refed_data && node->data->common.value_table->value_init;
if (has_refed_data)
{
@@ -5066,7 +4838,7 @@ g_type_class_get_private (GTypeClass *klass,
if (NODE_PARENT_TYPE (private_node))
{
parent_node = lookup_type_node_I (NODE_PARENT_TYPE (private_node));
- g_assert (parent_node->data && NODE_REFCOUNT (parent_node) > 0);
+ g_assert (parent_node->data);
if (G_UNLIKELY (private_node->data->class.class_private_size == parent_node->data->class.class_private_size))
{
diff --git a/gobject/gtype.h b/gobject/gtype.h
index 04e373385..9ed47a347 100644
--- a/gobject/gtype.h
+++ b/gobject/gtype.h
@@ -749,6 +749,8 @@ gboolean g_type_is_a (GType type,
#define g_type_is_a(a,b) ((a) == (b) || (g_type_is_a) ((a), (b)))
GOBJECT_AVAILABLE_IN_ALL
+gpointer g_type_class_get (GType type);
+GOBJECT_AVAILABLE_IN_ALL
gpointer g_type_class_ref (GType type);
GOBJECT_AVAILABLE_IN_ALL
gpointer g_type_class_peek (GType type);
@@ -765,6 +767,8 @@ GOBJECT_AVAILABLE_IN_ALL
gpointer g_type_interface_peek_parent (gpointer g_iface);
GOBJECT_AVAILABLE_IN_ALL
+gpointer g_type_default_interface_get (GType g_type);
+GOBJECT_AVAILABLE_IN_ALL
gpointer g_type_default_interface_ref (GType g_type);
GOBJECT_AVAILABLE_IN_ALL
gpointer g_type_default_interface_peek (GType g_type);