diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 53b7732e2..f48c2f00b 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -362,6 +362,13 @@ G_LOG_2_BASE_10 macros_misc G_INLINE_FUNC + +g_auto +g_autoptr +G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC +G_DEFINE_AUTO_CLEANUP_FREE_FUNC + G_STMT_START G_STMT_END diff --git a/glib/docs.c b/glib/docs.c index 43c9f27e2..d6811653e 100644 --- a/glib/docs.c +++ b/glib/docs.c @@ -2310,6 +2310,196 @@ * Defined to 1 if gcc-style visibility handling is supported. */ +/* g_auto(), g_autoptr() and helpers {{{1 */ + +/** + * g_auto: + * @typename: a supported variable type + * + * Helper to declare a variable with automatic cleanup. + * + * The variable is cleaned up in a way appropriate to its type when the + * variable goes out of scope. The type must support this. + * + * This feature is only supported on GCC and clang. This macro is not + * defined on other compilers and should not be used in programs that + * are intended to be portable to those compilers. + * + * This is meant to be used with stack-allocated structures and + * non-pointer types. For the (more commonly used) pointer version, see + * g_autoptr(). + * + * This macro can be used to avoid having to do explicit cleanups of + * local variables when exiting functions. It often vastly simplifies + * handling of error conditions, removing the need for various tricks + * such as 'goto out' or repeating of cleanup code. It is also helpful + * for non-error cases. + * + * Consider the following example: + * + * |[ + * GVariant * + * my_func(void) + * { + * g_auto(GQueue) queue = G_QUEUE_INIT; + * g_auto(GVariantBuilder) builder; + * + * g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + * + * ... + * + * if (error_condition) + * return NULL; + * + * ... + * + * return g_variant_builder_end (&builder); + * } + * ]| + * + * You must initialise the variable in some way -- either by use of an + * initialiser or by ensuring that an _init function will be called on + * it unconditionally before it goes out of scope. + * + * Since: 2.44 + */ + +/** + * g_autoptr: + * @typename: a supported variable type + * + * Helper to declare a pointer variable with automatic cleanup. + * + * The variable is cleaned up in a way appropriate to its type when the + * variable goes out of scope. The type must support this. + * + * This feature is only supported on GCC and clang. This macro is not + * defined on other compilers and should not be used in programs that + * are intended to be portable to those compilers. + * + * This is meant to be used to declare pointers to types with cleanup + * functions. The type of the variable is a pointer to @typename. You + * must not add your own '*'. + * + * This macro can be used to avoid having to do explicit cleanups of + * local variables when exiting functions. It often vastly simplifies + * handling of error conditions, removing the need for various tricks + * such as 'goto out' or repeating of cleanup code. It is also helpful + * for non-error cases. + * + * Consider the following example: + * + * |[ + * gboolean + * check_exists(GVariant *dict) + * { + * g_autoptr(GVariant) dirname; + * g_autoptr(GVariant) basename = NULL; + * g_autoptr(gchar) path = NULL; + * + * dirname = g_variant_lookup_value (dict, "dirname", G_VARIANT_TYPE_STRING); + * + * if (dirname == NULL) + * return FALSE; + * + * basename = g_variant_lookup_value (dict, "basename", G_VARIANT_TYPE_STRING); + * + * if (basename == NULL) + * return FALSE; + * + * path = g_build_filename (g_variant_get_string (dirname, NULL), + * g_variant_get_string (basename, NULL), + * NULL); + * + * return g_access (path, R_OK) == 0; + * } + * ]| + * + * You must initialise the variable in some way -- either by use of an + * initialiser or by ensuring that it is assigned to unconditionally + * before it goes out of scope. + * + * Since: 2.44 + */ + +/** + * G_DEFINE_AUTOPTR_CLEANUP_FUNC: + * @TypeName: a type name to define a g_autoptr() cleanup function for + * @func: the cleanup function + * + * Defines the appropriate cleanup function for a pointer type. + * + * The function will not be called if the variable to be cleaned up + * contains %NULL. + * + * This will typically be the _free() or _unref() function for the given + * type. + * + * With this definition, it will be possible to use g_autoptr() with + * @TypeName. + * + * |[ + * G_DEFINE_AUTOPTR_CLEANUP_FUNC(GObject, g_object_unref) + * ]| + * + * This macro should be used unconditionally; it is a no-op on compilers + * where cleanup is not supported. + * + * Since: 2.44 + */ + +/** + * G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC: + * @TypeName: a type name to define a g_auto() cleanup function for + * @func: the clear function + * + * Defines the appropriate cleanup function for a type. + * + * This will typically be the _clear() function for the given type. + * + * With this definition, it will be possible to use g_auto() with + * @TypeName. + * + * |[ + * G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(GQueue, g_queue_clear) + * ]| + * + * This macro should be used unconditionally; it is a no-op on compilers + * where cleanup is not supported. + * + * Since: 2.44 + */ + +/** + * G_DEFINE_AUTO_CLEANUP_FREE_FUNC: + * @TypeName: a type name to define a g_auto() cleanup function for + * @func: the free function + * @none: the "none" value for the type + * + * Defines the appropriate cleanup function for a type. + * + * With this definition, it will be possible to use g_auto() with + * @TypeName. + * + * This function will be rarely used. It is used with pointer-based + * typedefs and non-pointer types where the value of the variable + * represents a resource that must be freed. Two examples are #GStrv + * and file descriptors. + * + * @none specifies the "none" value for the type in question. It is + * probably something like %NULL or -1. If the variable is found to + * contain this value then the free function will not be called. + * + * |[ + * G_DEFINE_AUTO_CLEANUP_FREE_FUNC(GStrv, g_strfreev, NULL) + * ]| + * + * This macro should be used unconditionally; it is a no-op on compilers + * where cleanup is not supported. + * + * Since: 2.44 + */ + /* Windows Compatibility Functions {{{1 */ /** diff --git a/glib/gmacros.h b/glib/gmacros.h index 73202287e..5b53bb50f 100644 --- a/glib/gmacros.h +++ b/glib/gmacros.h @@ -373,4 +373,38 @@ #define GLIB_UNAVAILABLE(maj,min) G_UNAVAILABLE(maj,min) _GLIB_EXTERN #endif +#ifdef __GNUC__ + +/* these macros are private */ +#define _GLIB_AUTOPTR_FUNC_NAME(TypeName) glib_autoptr_cleanup_##TypeName +#define _GLIB_AUTOPTR_TYPENAME(TypeName) TypeName##_autoptr +#define _GLIB_AUTO_FUNC_NAME(TypeName) glib_auto_cleanup_##TypeName +#define _GLIB_CLEANUP(func) __attribute__((cleanup(func))) + +/* these macros are API */ +#define G_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, func) \ + typedef TypeName *_GLIB_AUTOPTR_TYPENAME(TypeName); \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + static inline void _GLIB_AUTOPTR_FUNC_NAME(TypeName) (TypeName **_ptr) { if (*_ptr) (func) (*_ptr); } \ + G_GNUC_END_IGNORE_DEPRECATIONS +#define G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(TypeName, func) \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + static inline void _GLIB_AUTO_FUNC_NAME(TypeName) (TypeName *_ptr) { (func) (_ptr); } \ + G_GNUC_END_IGNORE_DEPRECATIONS +#define G_DEFINE_AUTO_CLEANUP_FREE_FUNC(TypeName, func, none) \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + static inline void _GLIB_AUTO_FUNC_NAME(TypeName) (TypeName *_ptr) { if (*_ptr != none) (func) (*_ptr); } \ + G_GNUC_END_IGNORE_DEPRECATIONS +#define g_autoptr(TypeName) _GLIB_CLEANUP(_GLIB_AUTOPTR_FUNC_NAME(TypeName)) _GLIB_AUTOPTR_TYPENAME(TypeName) +#define g_auto(TypeName) _GLIB_CLEANUP(_GLIB_AUTO_FUNC_NAME(TypeName)) TypeName + +#else /* not GNU C */ + +#define G_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, func) +#define G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(TypeName, func) +#define G_DEFINE_AUTO_CLEANUP_FREE_FUNC(TypeName, func) + +/* no declaration of g_auto() or g_autoptr() here */ +#endif + #endif /* __G_MACROS_H__ */