[gtk/wip/baedert/for-master: 8/12] add GtkArray



commit 86acf31b7b93dc5a7c1c215bc429e1de34f45512
Author: Timm Bäder <mail baedert org>
Date:   Wed Apr 29 09:28:17 2020 +0200

    add GtkArray
    
    Try to use stack space if we can and only fall back to the GPtrArray if
    we must.

 gtk/gtkarrayimplprivate.h | 100 ++++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkmain.c             |  33 ++++++++-------
 2 files changed, 118 insertions(+), 15 deletions(-)
---
diff --git a/gtk/gtkarrayimplprivate.h b/gtk/gtkarrayimplprivate.h
new file mode 100644
index 0000000000..0027aa5b3e
--- /dev/null
+++ b/gtk/gtkarrayimplprivate.h
@@ -0,0 +1,100 @@
+#ifndef __GTK_ARRAY_IMPL_PRIVATE_H__
+#define __GTK_ARRAY_IMPL_PRIVATE_H__
+
+
+/* This is a dumbed-down GPtrArray, which takes some stack
+ * space to use. When using this, the general case should always
+ * be that the number of elements is lower than reversed_size.
+ * The GPtrArray should only be used in extreme cases.
+ */
+
+typedef struct
+{
+  guint reserved_size;
+  guint len;
+  void **stack_space;
+  GPtrArray *ptr_array;
+
+} GtkArray;
+
+
+static inline void
+gtk_array_init (GtkArray   *self,
+                void     **stack_space,
+                guint      reserved_size)
+{
+  self->reserved_size = reserved_size;
+  self->len = 0;
+  self->stack_space = stack_space;
+  self->ptr_array = NULL;
+}
+
+static inline void *
+gtk_array_index (GtkArray *self,
+                 guint     index)
+{
+  g_assert (index < self->len);
+
+  if (G_LIKELY (!self->ptr_array))
+    return self->stack_space[index];
+
+  return g_ptr_array_index (self->ptr_array, index);
+}
+
+static inline void
+gtk_array_add (GtkArray *self,
+               void     *element)
+{
+  if (G_LIKELY (self->len < self->reserved_size))
+    {
+      self->stack_space[self->len] = element;
+      self->len++;
+      return;
+    }
+
+  /* Need to fall back to the GPtrArray */
+  if (G_UNLIKELY (!self->ptr_array))
+    {
+      guint i;
+
+      self->ptr_array = g_ptr_array_new_full (self->reserved_size, NULL);
+
+      /* Copy elements from stack space to GPtrArray */
+      for (i = 0; i < self->len; i++)
+        g_ptr_array_add (self->ptr_array, self->stack_space[i]);
+    }
+
+  g_ptr_array_add (self->ptr_array, element);
+  self->len++; /* We still count self->len */
+}
+
+static inline void
+gtk_array_free (GtkArray       *self,
+                GDestroyNotify  element_free_func)
+{
+  guint i;
+
+  if (G_LIKELY (!self->ptr_array))
+    {
+      if (element_free_func)
+        {
+          for (i = 0; i < self->len; i++)
+            element_free_func (self->stack_space[i]);
+        }
+
+      return;
+    }
+
+  g_assert (self->ptr_array);
+
+  if (element_free_func)
+    {
+      for (i = 0; i < self->ptr_array->len; i++)
+        element_free_func (g_ptr_array_index (self->ptr_array, i));
+    }
+
+  g_ptr_array_free (self->ptr_array, TRUE);
+}
+
+
+#endif
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index f8a6dfac35..518f3aefbf 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -95,6 +95,7 @@
 #include "gdk/gdk-private.h"
 #include "gsk/gskprivate.h"
 #include "gsk/gskrendernodeprivate.h"
+#include "gtkarrayimplprivate.h"
 
 #include <locale.h>
 
@@ -1310,7 +1311,8 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
   double x, y;
   GtkWidget *prev;
   gboolean seen_ancestor;
-  GPtrArray *targets;
+  GtkArray target_array;
+  GtkWidget *stack_targets[16];
   int i;
 
   if (old_target == new_target)
@@ -1364,19 +1366,19 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
       widget = _gtk_widget_get_parent (widget);
     }
 
-  targets = g_ptr_array_new_full (16, NULL);
+  gtk_array_init (&target_array, (void**)stack_targets, 16);
   for (widget = new_target; widget; widget = _gtk_widget_get_parent (widget))
-    g_ptr_array_add (targets, widget);
+    gtk_array_add (&target_array, widget);
 
   crossing.direction = GTK_CROSSING_IN;
 
   seen_ancestor = FALSE;
-  for (i = (int)targets->len - 1; i >= 0; i--)
+  for (i = (int)target_array.len - 1; i >= 0; i--)
     {
-      widget = g_ptr_array_index (targets, i);
+      widget = gtk_array_index (&target_array, i);
 
-      if (i < (int)targets->len - 1)
-        crossing.new_descendent = g_ptr_array_index (targets, i + 1);
+      if (i < (int)target_array.len - 1)
+        crossing.new_descendent = gtk_array_index (&target_array, i + 1);
       else
         crossing.new_descendent = NULL;
 
@@ -1405,7 +1407,7 @@ gtk_synthesize_crossing_events (GtkRoot         *toplevel,
         gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_PRELIGHT, FALSE);
     }
 
-  g_ptr_array_free (targets, TRUE);
+  gtk_array_free (&target_array, NULL);
 }
 
 static GtkWidget *
@@ -2130,11 +2132,12 @@ propagate_event_down (GtkWidget *widget,
 {
   gint handled_event = FALSE;
   GtkWidget *target = widget;
-  GPtrArray *widgets;
+  GtkArray widget_array;
+  GtkWidget *stack_widgets[16];
   int i;
 
-  widgets = g_ptr_array_new_full (16, g_object_unref);
-  g_ptr_array_add (widgets, g_object_ref (widget));
+  gtk_array_init (&widget_array, (void**)stack_widgets, 16);
+  gtk_array_add (&widget_array, g_object_ref (widget));
 
   for (;;)
     {
@@ -2142,16 +2145,16 @@ propagate_event_down (GtkWidget *widget,
       if (!widget)
         break;
 
-      g_ptr_array_add (widgets, g_object_ref (widget));
+      gtk_array_add (&widget_array, g_object_ref (widget));
 
       if (widget == topmost)
         break;
     }
 
-  i = (int)widgets->len - 1;
+  i = widget_array.len - 1;
   for (;;)
     {
-      widget = g_ptr_array_index (widgets, i);
+      widget = gtk_array_index (&widget_array, i);
 
       if (!_gtk_widget_is_sensitive (widget))
         {
@@ -2177,7 +2180,7 @@ propagate_event_down (GtkWidget *widget,
       i--;
     }
 
-  g_ptr_array_free (widgets, TRUE);
+  gtk_array_free (&widget_array, g_object_unref);
 
   return handled_event;
 }


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