diff --git a/glib/gtype.c b/glib/gtype.c index c9f9527e7..afa327980 100644 --- a/glib/gtype.c +++ b/glib/gtype.c @@ -1999,7 +1999,24 @@ g_type_free_instance (GTypeInstance *instance) NODE_NAME (node)); return; } - + + if (G_IS_TYPE_FINALIZABLE (instance)) + { + GTypeFinalizableInterface *iface = G_TYPE_FINALIZABLE_GET_IFACE (instance); + GType parent_type = g_type_parent (class->g_type); + + if (iface->finalize != NULL) + iface->finalize ((GTypeFinalizable *) instance); + + iface = g_type_interface_peek_parent (iface); + while (iface != NULL) + { + if (iface->finalize != NULL) + iface->finalize ((GTypeFinalizable *) instance); + iface = g_type_interface_peek_parent (iface); + } + } + instance->g_class = NULL; private_size = node->data->instance.private_size; ivar_size = node->data->instance.instance_size; @@ -4972,3 +4989,10 @@ g_type_init_internal (void) _g_value_transforms_init (); } + +static void +g_type_finalizable_default_init (GTypeFinalizableInterface *iface) +{ +} + +G_DEFINE_INTERFACE (GTypeFinalizable, g_type_finalizable, G_TYPE_INVALID) diff --git a/glib/gtype.h b/glib/gtype.h index 0c8d7923c..69f4cb3fc 100644 --- a/glib/gtype.h +++ b/glib/gtype.h @@ -427,6 +427,8 @@ typedef struct _GInterfaceInfo GInterfaceInfo; typedef struct _GTypeValueTable GTypeValueTable; typedef struct _GTypeQuery GTypeQuery; +typedef struct _GTypeFinalizable GTypeFinalizable; +typedef struct _GTypeFinalizableInterface GTypeFinalizableInterface; /* Basic Type Structures */ @@ -480,6 +482,34 @@ struct _GTypeQuery guint instance_size; }; +/** + * GTypeFinalizable: + * + * An interface for finalizable types. + * + * Instance types that allocate data on the instance structure and wish + * to free their resources when [func@GObject.type_free_instance] is called, + * should implement the [vfunc@GObject.TypeFinalizable.finalize] virtual + * function of this interface. + */ + +/** + * GTypeFinalizableInterface: + * + * An interface for finalizable types. + */ +struct _GTypeFinalizableInterface +{ + GTypeInterface parent_iface; + + /** + * GTypeFinalizableInterface::finalize: + * @self: the instance to finalize + * + * Finalizes the instance data. + */ + void (* finalize) (GTypeFinalizable *self); +}; /* Casts, checks and accessors for structured types * usage of these macros is reserved to type implementations only @@ -2718,4 +2748,22 @@ const gchar * g_type_name_from_class (GTypeClass *g_class); */ #define GTYPE_TO_POINTER(t) ((gpointer) (guintptr) (t)) GLIB_AVAILABLE_MACRO_IN_2_80 +GLIB_AVAILABLE_IN_ALL +GType g_type_finalizable_get_type (void) G_GNUC_CONST; + +G_GNUC_UNUSED static inline GTypeFinalizable * +G_TYPE_FINALIZABLE (gpointer ptr) { + return G_TYPE_CHECK_INSTANCE_CAST (ptr, g_type_finalizable_get_type (), GTypeFinalizable); +} + +G_GNUC_UNUSED static inline gboolean +G_IS_TYPE_FINALIZABLE (gpointer ptr) { + return G_TYPE_CHECK_INSTANCE_TYPE (ptr, g_type_finalizable_get_type ()); +} + +G_GNUC_UNUSED static inline GTypeFinalizableInterface * +G_TYPE_FINALIZABLE_GET_IFACE (gpointer ptr) { + return G_TYPE_INSTANCE_GET_INTERFACE (ptr, g_type_finalizable_get_type (), GTypeFinalizableInterface); +} + G_END_DECLS