[glib/cheaper-source-names] mainloop: Add g_source_set_static_name




commit 067a2a8fc84954ab4da5753d6b488e5a62d36be4
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Jul 24 08:38:11 2021 -0400

    mainloop: Add g_source_set_static_name
    
    g_source_set_name duplicates the string, and this is
    showing up as one of the more prominent sources of strdups
    in GTK profiles, despite all the names we use being literals.
    
    Add a variant that avoids the overhead.

 glib/gmain.c          | 81 +++++++++++++++++++++++++++++++++++++--------------
 glib/gmain.h          |  3 ++
 glib/tests/mainloop.c |  3 ++
 3 files changed, 65 insertions(+), 22 deletions(-)
---
diff --git a/glib/gmain.c b/glib/gmain.c
index 4efa9ad6f..f36da1eea 100644
--- a/glib/gmain.c
+++ b/glib/gmain.c
@@ -364,6 +364,8 @@ struct _GSourcePrivate
   GSList *fds;
 
   GSourceDisposeFunc dispose;
+
+  gboolean static_name;
 };
 
 typedef struct _GSourceIter
@@ -2059,6 +2061,41 @@ g_source_get_can_recurse (GSource  *source)
   return (source->flags & G_SOURCE_CAN_RECURSE) != 0;
 }
 
+static void
+g_source_set_name_full (GSource    *source,
+                        const char *name,
+                        gboolean    is_static)
+{
+  GMainContext *context;
+
+  g_return_if_fail (source != NULL);
+  g_return_if_fail (g_atomic_int_get (&source->ref_count) > 0);
+
+  context = source->context;
+
+  if (context)
+    LOCK_CONTEXT (context);
+
+  TRACE (GLIB_SOURCE_SET_NAME (source, name));
+
+  /* setting back to NULL is allowed, just because it's
+   * weird if get_name can return NULL but you can't
+   * set that.
+   */
+
+  if (!source->priv->static_name)
+    g_free (source->name);
+
+  if (is_static)
+    source->name = (char *)name;
+  else
+    source->name = g_strdup (name);
+
+  source->priv->static_name = is_static;
+
+  if (context)
+    UNLOCK_CONTEXT (context);
+}
 
 /**
  * g_source_set_name:
@@ -2082,34 +2119,33 @@ g_source_get_can_recurse (GSource  *source)
  * the value, and changing the value will free it while the other thread
  * may be attempting to use it.
  *
+ * Also see g_source_set_static_name().
+ *
  * Since: 2.26
  **/
 void
 g_source_set_name (GSource    *source,
                    const char *name)
 {
-  GMainContext *context;
-
-  g_return_if_fail (source != NULL);
-  g_return_if_fail (g_atomic_int_get (&source->ref_count) > 0);
-
-  context = source->context;
-
-  if (context)
-    LOCK_CONTEXT (context);
-
-  TRACE (GLIB_SOURCE_SET_NAME (source, name));
-
-  /* setting back to NULL is allowed, just because it's
-   * weird if get_name can return NULL but you can't
-   * set that.
-   */
-
-  g_free (source->name);
-  source->name = g_strdup (name);
+  g_source_set_name_full (source, name, FALSE);
+}
 
-  if (context)
-    UNLOCK_CONTEXT (context);
+/**
+ * g_source_set_static_name:
+ * @source: a #GSource
+ * @name: debug name for the source
+ *
+ * A variant of g_source_set_name() that does not
+ * duplicate the @name, and can only be used with
+ * string literals.
+ *
+ * Since: 2.70
+ */
+void
+g_source_set_static_name (GSource    *source,
+                          const char *name)
+{
+  g_source_set_name_full (source, name, TRUE);
 }
 
 /**
@@ -2284,7 +2320,8 @@ g_source_unref_internal (GSource      *source,
           g_warn_if_fail (old_ref_count == 1);
         }
 
-      g_free (source->name);
+      if (!source->priv->static_name)
+        g_free (source->name);
       source->name = NULL;
 
       g_slist_free (source->poll_fds);
diff --git a/glib/gmain.h b/glib/gmain.h
index 8428e01a4..8e15f3da4 100644
--- a/glib/gmain.h
+++ b/glib/gmain.h
@@ -605,6 +605,9 @@ gboolean g_source_is_destroyed    (GSource        *source);
 GLIB_AVAILABLE_IN_ALL
 void                 g_source_set_name       (GSource        *source,
                                               const char     *name);
+GLIB_AVAILABLE_IN_2_70
+void                 g_source_set_static_name (GSource        *source,
+                                               const char     *name);
 GLIB_AVAILABLE_IN_ALL
 const char *         g_source_get_name       (GSource        *source);
 GLIB_AVAILABLE_IN_ALL
diff --git a/glib/tests/mainloop.c b/glib/tests/mainloop.c
index 77e21f548..4ef0e9c7d 100644
--- a/glib/tests/mainloop.c
+++ b/glib/tests/mainloop.c
@@ -83,6 +83,9 @@ test_maincontext_basic (void)
   g_assert_true (g_source_get_can_recurse (source));
   g_assert_cmpstr (g_source_get_name (source), ==, "d");
 
+  g_source_set_static_name (source, "still d");
+  g_assert_cmpstr (g_source_get_name (source), ==, "still d");
+
   g_assert_null (g_main_context_find_source_by_user_data (ctx, NULL));
   g_assert_null (g_main_context_find_source_by_funcs_user_data (ctx, &funcs, NULL));
 


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