[glib/task-strdup-avoidance: 3/3] gio: Add g_task_set_static_name




commit 4bbc8b22ff2ce92d3e6313d630362e66c546db5d
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Aug 27 21:34:58 2022 -0400

    gio: 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.

 gio/gtask.c | 39 +++++++++++++++++++++++++++++++++------
 gio/gtask.h | 17 ++++++++++++++++-
 2 files changed, 49 insertions(+), 7 deletions(-)
---
diff --git a/gio/gtask.c b/gio/gtask.c
index 3bc6bf6f46..04ce8c965b 100644
--- a/gio/gtask.c
+++ b/gio/gtask.c
@@ -588,6 +588,7 @@ struct _GTask {
   gboolean check_cancellable : 1;
   gboolean synchronous : 1;
   gboolean blocking_other_task : 1;
+  gboolean 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.74
+ */
+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 235e6626dd..b8f91895cf 100644
--- a/gio/gtask.h
+++ b/gio/gtask.h
@@ -79,6 +79,9 @@ void          g_task_set_source_tag        (GTask               *task,
 GLIB_AVAILABLE_IN_2_60
 void          g_task_set_name              (GTask               *task,
                                             const gchar         *name);
+GLIB_AVAILABLE_IN_2_74
+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,9 +89,21 @@ 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_74
+#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
 
 GLIB_AVAILABLE_IN_2_36
 gpointer      g_task_get_source_object     (GTask               *task);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]