From 99c7d6086922a53b0ce8aa90e5d147872724eafb Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sat, 27 Aug 2022 21:34:58 -0400 Subject: [PATCH] gtask: Add g_task_set_static_name() Similar to g_source_set_static_name, this avoids strdup overhead for debug-only information in possibly hot code paths. We also add a macro wrapper for g_task_set_name that uses __builtin_constant_p to decide whether to use g_task_set_name or g_task_set_static_name. --- docs/reference/gio/gio-sections-common.txt | 1 + gio/gtask.c | 39 ++++++++++++++++++---- gio/gtask.h | 17 +++++++++- 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 0ef50d747..a6ff920ca 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -4562,6 +4562,7 @@ g_task_set_check_cancellable g_task_set_return_on_cancel g_task_set_source_tag g_task_set_name +g_task_set_static_name g_task_report_error g_task_report_new_error diff --git a/gio/gtask.c b/gio/gtask.c index 5464a1cb0..1d5b37e85 100644 --- a/gio/gtask.c +++ b/gio/gtask.c @@ -588,6 +588,7 @@ struct _GTask { guint check_cancellable : 1; guint synchronous : 1; guint blocking_other_task : 1; + guint name_is_static : 1; GError *error; union { @@ -660,7 +661,8 @@ g_task_finalize (GObject *object) g_clear_object (&task->source_object); g_clear_object (&task->cancellable); - g_free (task->name); + if (!task->name_is_static) + g_free (task->name); if (task->context) g_main_context_unref (task->context); @@ -769,7 +771,7 @@ g_task_report_error (gpointer source_object, task = g_task_new (source_object, NULL, callback, callback_data); g_task_set_source_tag (task, source_tag); - g_task_set_name (task, G_STRFUNC); + g_task_set_static_name (task, G_STRFUNC); g_task_return_error (task, error); g_object_unref (task); } @@ -1028,16 +1030,41 @@ void * Since: 2.60 */ void -g_task_set_name (GTask *task, - const gchar *name) +(g_task_set_name) (GTask *task, + const char *name) { - gchar *new_name; + char *new_name; g_return_if_fail (G_IS_TASK (task)); new_name = g_strdup (name); - g_free (task->name); + if (!task->name_is_static) + g_free (task->name); task->name = g_steal_pointer (&new_name); + task->name_is_static = FALSE; +} + +/** + * g_task_set_static_name: + * @task: a #GTask + * @name: (nullable): a human readable name for the task. Must be a string literal + * + * Sets @task’s name, used in debugging and profiling. + * + * This is a variant of g_task_set_name() that avoids copying @name. + * + * Since: 2.76 + */ +void +g_task_set_static_name (GTask *task, + const char *name) +{ + g_return_if_fail (G_IS_TASK (task)); + + if (!task->name_is_static) + g_free (task->name); + task->name = (char *) name; + task->name_is_static = TRUE; } /** diff --git a/gio/gtask.h b/gio/gtask.h index 0f17ad53f..368d60ff2 100644 --- a/gio/gtask.h +++ b/gio/gtask.h @@ -79,6 +79,9 @@ void g_task_set_source_tag (GTask *task, GIO_AVAILABLE_IN_2_60 void g_task_set_name (GTask *task, const gchar *name); +GIO_AVAILABLE_IN_2_76 +void g_task_set_static_name (GTask *task, + const gchar *name); /* Macro wrapper to set the task name when setting the source tag. */ #if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_60 @@ -86,10 +89,22 @@ void g_task_set_name (GTask *task, GTask *_task = (task); \ (g_task_set_source_tag) (_task, tag); \ if (g_task_get_name (_task) == NULL) \ - g_task_set_name (_task, G_STRINGIFY (tag)); \ + g_task_set_static_name (_task, G_STRINGIFY (tag)); \ } G_STMT_END #endif +#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_76 +#if defined (__GNUC__) && (__GNUC__ >= 2) +#define g_task_set_name(task, name) G_STMT_START { \ + GTask *_task = (task); \ + if (__builtin_constant_p (name)) \ + g_task_set_static_name (_task, name); \ + else \ + g_task_set_name (_task, name); \ +} G_STMT_END +#endif +#endif + GIO_AVAILABLE_IN_2_36 gpointer g_task_get_source_object (GTask *task); GIO_AVAILABLE_IN_2_36