diff --git a/gobject/gtype.c b/gobject/gtype.c index cbce0acbd..22a998222 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -153,10 +153,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, @@ -192,7 +188,6 @@ typedef enum /* --- structures --- */ struct _TypeNode { - guint ref_count; /* (atomic) */ #ifdef G_ENABLE_DEBUG guint instance_count; /* (atomic) */ #endif @@ -228,7 +223,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) @@ -297,7 +291,7 @@ struct _ClassData CommonData common; guint16 class_size; guint16 class_private_size; - int init_state; /* (atomic) - g_type_class_ref reads it unlocked */ + int init_state; /* (atomic) - g_type_class_get reads it unlocked */ GBaseInitFunc class_init_base; GBaseFinalizeFunc class_finalize_base; GClassInitFunc class_init; @@ -311,7 +305,7 @@ struct _InstanceData CommonData common; guint16 class_size; guint16 class_private_size; - int init_state; /* (atomic) - g_type_class_ref reads it unlocked */ + int init_state; /* (atomic) - g_type_class_get reads it unlocked */ GBaseInitFunc class_init_base; GBaseFinalizeFunc class_finalize_base; GClassInitFunc class_init; @@ -1204,7 +1198,7 @@ type_data_make_W (TypeNode *node, !((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) & GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags)))); - g_atomic_int_set ((int *) &node->ref_count, 1); + g_assert (node->data->common.value_table != NULL); /* paranoid */ } static inline void @@ -1240,27 +1234,6 @@ 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)); - - return TRUE; } static gboolean @@ -1776,29 +1749,6 @@ type_iface_retrieve_holder_info_Wm (TypeNode *iface, return iholder; /* we don't modify write lock upon returning NULL */ } -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) { @@ -1892,7 +1842,7 @@ g_type_create_instance (GType type) maybe_issue_deprecation_warning (type); } - class = g_type_class_ref (type); + class = g_type_class_get (type); /* We allocate the 'private' areas before the normal instance data, in * reverse order. This allows the private area of a particular class @@ -2035,8 +1985,6 @@ g_type_free_instance (GTypeInstance *instance) g_atomic_int_add ((int *) &node->instance_count, -1); } #endif - - g_type_class_unref (class); } static void @@ -2159,41 +2107,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) @@ -2354,193 +2267,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 @@ -2977,23 +2703,28 @@ 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: 2.84 */ gpointer -g_type_class_ref (GType type) +g_type_class_get (GType type) { TypeNode *node; GType ptype; - gboolean holds_ref; GTypeClass *pclass; /* optimize for common code path */ @@ -3005,14 +2736,11 @@ g_type_class_ref (GType type) return NULL; } - if (G_LIKELY (type_data_ref_U (node))) + if (G_LIKELY (node->data != NULL)) { if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)) return node->data->class.class; - holds_ref = TRUE; } - else - holds_ref = FALSE; /* here, we either have node->data->class.class == NULL, or a recursive * call to g_type_class_ref() with a partly initialized class, or @@ -3023,49 +2751,58 @@ 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); - if (!holds_ref) - type_data_ref_Wm (node); + type_data_ref_Wm (node); if (!node->data->class.class) /* class uninitialized */ type_class_init_Wm (node, pclass); G_WRITE_UNLOCK (&type_rw_lock); - if (pclass) - g_type_class_unref (pclass); - g_rec_mutex_unlock (&class_init_rec_mutex); return node->data->class.class; } +/** + * 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: 2.84: 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: 2.84: Type class reference counting has been removed and type + * classes now cannot be finalized. This function no longer does 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)); } /** @@ -3073,55 +2810,53 @@ 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: 2.84: Type class reference counting has been removed and type + * classes now cannot be finalized. This function no longer does 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 * - * This function is essentially the same as g_type_class_ref(), - * except that the classes reference count isn't incremented. + * Retrieves the class for a give type. + * + * This function is essentially the same as g_type_class_get(), + * 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 + * Returns: (type GObject.TypeClass) (transfer none) (nullable): the + * #GTypeClass structure for the given type ID or %NULL if the class + * does not currently exist */ gpointer g_type_class_peek (GType type) { TypeNode *node; - gpointer class; node = lookup_type_node_I (type); - if (node && node->is_classed && NODE_REFCOUNT (node) && - g_atomic_int_get (&node->data->class.init_state) == INITIALIZED) - /* ref_count _may_ be 0 */ - class = node->data->class.class; - else - class = NULL; + if (node && node->is_classed) + { + if (node->data == NULL) + return NULL; + + if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)) + return node->data->class.class; + } - return class; + return NULL; } /** @@ -3131,9 +2866,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 */ @@ -3141,36 +2876,42 @@ gpointer g_type_class_peek_static (GType type) { TypeNode *node; - gpointer class; node = lookup_type_node_I (type); - if (node && node->is_classed && NODE_REFCOUNT (node) && - /* 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; - - return class; + if (node && node->is_classed) + { + if (node->data == NULL) + return NULL; + + /* peek only static types */ + if (node->plugin != NULL) + return NULL; + + if (G_LIKELY (g_atomic_int_get (&node->data->class.init_state) == INITIALIZED)) + return node->data->class.class; + } + + return NULL; } /** * 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) @@ -3207,9 +2948,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, @@ -3237,14 +2978,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. + * of the instance type to which @g_iface belongs. * - * 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 + * 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) @@ -3285,12 +3027,43 @@ g_type_interface_peek_parent (gpointer g_iface) * * Since: 2.4 * + * Deprecated: 2.84: 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. + * + * Since: 2.84 + */ +gpointer +g_type_default_interface_get (GType g_type) { TypeNode *node; gpointer dflt_vtable; @@ -3298,8 +3071,7 @@ g_type_default_interface_ref (GType g_type) 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'", @@ -3317,8 +3089,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); @@ -3336,8 +3106,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) @@ -3346,7 +3116,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; @@ -3360,38 +3130,33 @@ g_type_default_interface_peek (GType g_type) * structure for an interface, as returned by g_type_default_interface_ref() * * Decrements the reference count for the type corresponding to the - * interface default vtable @g_iface. If the type is dynamic, then - * when no one is using the interface and all references have - * been released, the finalize function for the interface's default - * vtable (the @class_finalize member of #GTypeInfo) will be called. + * interface default vtable @g_iface. + * + * If the type is dynamic, then when no one is using the interface and all + * references have been released, the finalize function for the interface's + * default vtable (the @class_finalize member of #GTypeInfo) will be called. * * Since: 2.4 + * + * Deprecated: 2.84: Interface reference counting has been removed and + * interface types now cannot be finalized. This function no longer does + * 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)); } /** * g_type_name: * @type: type to return name for * - * Get the unique name that is assigned to a type ID. Note that this - * function (like all other GType API) cannot cope with invalid type - * IDs. %G_TYPE_INVALID may be passed to this function, as may be any - * other validly registered type ID, but randomized type IDs should - * not be passed in and will most likely lead to a crash. + * Get the unique name that is assigned to a type ID. + * + * Note that this function (like all other GType API) cannot cope with + * invalid type IDs. %G_TYPE_INVALID may be passed to this function, as + * may be any other validly registered type ID, but randomized type IDs + * should not be passed in and will most likely lead to a crash. * * Returns: (nullable): static type name or %NULL */ @@ -4288,7 +4053,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)) @@ -4343,25 +4108,26 @@ 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; + gboolean has_data, has_table; - if (node && NODE_REFCOUNT (node) && node->mutatable_check_cache) + if (node != NULL && 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_table = has_refed_data && node->data->common.value_table->value_init; - if (has_refed_data) + has_data = node != NULL && node->data != NULL; + has_table = has_data && node->data->common.value_table->value_init; + if (has_data) { if (has_table) vtable = node->data->common.value_table; @@ -4391,7 +4157,7 @@ g_type_value_table_peek (GType type) if (!node) g_critical (G_STRLOC ": type id '%" G_GUINTPTR_FORMAT "' is invalid", (guintptr) type); - if (!has_refed_data) + if (!has_data) g_critical ("can't peek value table for type '%s' which is not currently referenced", type_descriptive_name_I (type)); @@ -5039,7 +4805,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 02a718464..76c043565 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -759,6 +759,8 @@ gboolean g_type_is_a (GType type, /* Hoist exact GType comparisons into the caller */ #define g_type_is_a(a,b) ((a) == (b) || (g_type_is_a) ((a), (b))) +GOBJECT_AVAILABLE_IN_2_84 +gpointer g_type_class_get (GType type); GOBJECT_AVAILABLE_IN_ALL gpointer g_type_class_ref (GType type); GOBJECT_AVAILABLE_IN_ALL @@ -775,6 +777,8 @@ gpointer g_type_interface_peek (gpointer instance_ GOBJECT_AVAILABLE_IN_ALL gpointer g_type_interface_peek_parent (gpointer g_iface); +GOBJECT_AVAILABLE_IN_2_84 +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