From: Lukáš Tyrychtr Date: Fri, 16 Sep 2022 14:29:53 +0000 (+0200) Subject: stack: Use a pointer array for children X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~8^2~9^2~9 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=4cd9fd9b1534be4bfee2e929b443478186390fdf;p=gtk4.git stack: Use a pointer array for children Reduce our dependency on linked lists; pointer arrays are better at cache locality. Additionally, we can avoid quadratic behaviors when finding a child at a given index. --- diff --git a/gtk/gtkstack.c b/gtk/gtkstack.c index 2d2de8990d..b43950725e 100644 --- a/gtk/gtkstack.c +++ b/gtk/gtkstack.c @@ -139,7 +139,7 @@ struct _GtkStackClass { }; typedef struct { - GList *children; + GPtrArray *children; GtkStackPage *visible_child; @@ -569,7 +569,7 @@ gtk_stack_pages_get_n_items (GListModel *model) GtkStackPages *pages = GTK_STACK_PAGES (model); GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack); - return g_list_length (priv->children); + return priv->children->len; } static gpointer @@ -580,11 +580,12 @@ gtk_stack_pages_get_item (GListModel *model, GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack); GtkStackPage *page; - page = g_list_nth_data (priv->children, position); - if (!page) + if (position > priv->children->len - 1) return NULL; + page = g_ptr_array_index (priv->children, position); + return g_object_ref (page); } @@ -604,9 +605,12 @@ gtk_stack_pages_is_selected (GtkSelectionModel *model, GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack); GtkStackPage *page; - page = g_list_nth_data (priv->children, position); + if (position > priv->children->len - 1) + return FALSE; + + page = g_ptr_array_index (priv->children, position); - return page && page == priv->visible_child; + return page == priv->visible_child; } static void set_visible_child (GtkStack *stack, @@ -623,7 +627,7 @@ gtk_stack_pages_select_item (GtkSelectionModel *model, GtkStackPrivate *priv = gtk_stack_get_instance_private (pages->stack); GtkStackPage *page; - page = g_list_nth_data (priv->children, position); + page = g_ptr_array_index (priv->children, position); set_visible_child (pages->stack, page, priv->transition_type, priv->transition_duration); @@ -657,7 +661,7 @@ gtk_stack_pages_get_property (GObject *object, case PAGES_PROP_N_ITEMS: g_value_set_uint (value, gtk_stack_pages_get_n_items (G_LIST_MODEL (self))); - break; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -768,7 +772,7 @@ gtk_stack_accessible_get_child_at_index (GtkAccessible *accessible, guint index) { GtkStack *stack = GTK_STACK (accessible); GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); - GtkStackPage *page = g_list_nth_data (priv->children, index); + GtkStackPage *page = g_ptr_array_index (priv->children, index); return GTK_ACCESSIBLE (page); } @@ -788,7 +792,7 @@ gtk_stack_dispose (GObject *obj) GtkStack *stack = GTK_STACK (obj); GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); GtkWidget *child; - guint n_pages = g_list_length (priv->children); + guint n_pages = priv->children->len; while ((child = gtk_widget_get_first_child (GTK_WIDGET (stack)))) stack_remove (stack, child, TRUE); @@ -813,6 +817,8 @@ gtk_stack_finalize (GObject *obj) gtk_stack_unschedule_ticks (stack); + g_ptr_array_free (priv->children, TRUE); + G_OBJECT_CLASS (gtk_stack_parent_class)->finalize (obj); } @@ -1028,11 +1034,11 @@ find_child_info_for_widget (GtkStack *stack, { GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); GtkStackPage *info; - GList *l; + guint idx; - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - info = l->data; + info = g_ptr_array_index (priv->children, idx); if (info->widget == child) return info; } @@ -1347,7 +1353,7 @@ set_visible_child (GtkStack *stack, GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); GtkStackPage *info; GtkWidget *widget = GTK_WIDGET (stack); - GList *l; + guint idx; GtkWidget *focus; gboolean contains_focus = FALSE; guint old_pos = GTK_INVALID_LIST_POSITION; @@ -1362,9 +1368,9 @@ set_visible_child (GtkStack *stack, /* If none, pick first visible */ if (child_info == NULL) { - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - info = l->data; + info = g_ptr_array_index (priv->children, idx); if (gtk_widget_get_visible (info->widget)) { child_info = info; @@ -1379,9 +1385,9 @@ set_visible_child (GtkStack *stack, if (priv->pages) { guint position; - for (l = priv->children, position = 0; l != NULL; l = l->next, position++) + for (idx = 0, position = 0; idx < priv->children->len; idx++, position++) { - info = l->data; + info = g_ptr_array_index (priv->children, idx); if (info == priv->visible_child) old_pos = position; else if (info == child_info) @@ -1449,14 +1455,14 @@ set_visible_child (GtkStack *stack, else if (is_direction_dependent_transition (transition_type)) { gboolean i_first = FALSE; - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - if (child_info == l->data) + if (child_info == g_ptr_array_index (priv->children, idx)) { i_first = TRUE; break; } - if (priv->last_visible_child == l->data) + if (priv->last_visible_child == g_ptr_array_index (priv->children, idx)) break; } @@ -1625,15 +1631,15 @@ gtk_stack_add_page (GtkStack *stack, GtkStackPage *child_info) { GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); - GList *l; + guint idx; g_return_if_fail (child_info->widget != NULL); if (child_info->name) { - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - GtkStackPage *info = l->data; + GtkStackPage *info = g_ptr_array_index (priv->children, idx); if (info->name && g_strcmp0 (info->name, child_info->name) == 0) { @@ -1643,14 +1649,14 @@ gtk_stack_add_page (GtkStack *stack, } } - priv->children = g_list_append (priv->children, g_object_ref (child_info)); + g_ptr_array_add (priv->children, g_object_ref (child_info)); gtk_widget_set_child_visible (child_info->widget, FALSE); gtk_widget_set_parent (child_info->widget, GTK_WIDGET (stack)); if (priv->pages) { - g_list_model_items_changed (G_LIST_MODEL (priv->pages), g_list_length (priv->children) - 1, 0, 1); + g_list_model_items_changed (G_LIST_MODEL (priv->pages), priv->children->len - 1, 0, 1); g_object_notify_by_pspec (G_OBJECT (priv->pages), pages_properties[PAGES_PROP_N_ITEMS]); } @@ -1694,7 +1700,7 @@ stack_remove (GtkStack *stack, g_clear_object (&child_info->widget); - priv->children = g_list_remove (priv->children, child_info); + g_ptr_array_remove (priv->children, child_info); g_object_unref (child_info); @@ -1716,16 +1722,15 @@ gtk_stack_remove (GtkStack *stack, GtkWidget *child) { GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); - GList *l; guint position; g_return_if_fail (GTK_IS_STACK (stack)); g_return_if_fail (GTK_IS_WIDGET (child)); g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (stack)); - for (l = priv->children, position = 0; l; l = l->next, position++) + for (position = 0; position < priv->children->len; position++) { - GtkStackPage *page = l->data; + GtkStackPage *page = g_ptr_array_index (priv->children, position); if (page->widget == child) break; } @@ -1773,14 +1778,14 @@ gtk_stack_get_child_by_name (GtkStack *stack, { GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); GtkStackPage *info; - GList *l; + guint idx; g_return_val_if_fail (GTK_IS_STACK (stack), NULL); g_return_val_if_fail (name != NULL, NULL); - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - info = l->data; + info = g_ptr_array_index (priv->children, idx); if (info->name && strcmp (info->name, name) == 0) return info->widget; } @@ -2191,7 +2196,7 @@ gtk_stack_set_visible_child_full (GtkStack *stack, { GtkStackPrivate *priv = gtk_stack_get_instance_private (stack); GtkStackPage *child_info, *info; - GList *l; + guint idx; g_return_if_fail (GTK_IS_STACK (stack)); @@ -2199,9 +2204,9 @@ gtk_stack_set_visible_child_full (GtkStack *stack, return; child_info = NULL; - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - info = l->data; + info = g_ptr_array_index (priv->children, idx); if (info->name != NULL && strcmp (info->name, name) == 0) { @@ -2230,13 +2235,13 @@ gtk_stack_compute_expand (GtkWidget *widget, gboolean hexpand, vexpand; GtkStackPage *child_info; GtkWidget *child; - GList *l; + guint idx; hexpand = FALSE; vexpand = FALSE; - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - child_info = l->data; + child_info = g_ptr_array_index (priv->children, idx); child = child_info->widget; if (!hexpand && @@ -2668,14 +2673,14 @@ gtk_stack_measure (GtkWidget *widget, GtkStackPage *child_info; GtkWidget *child; int child_min, child_nat; - GList *l; + guint idx; *minimum = 0; *natural = 0; - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - child_info = l->data; + child_info = g_ptr_array_index (priv->children, idx); child = child_info->widget; if (!priv->homogeneous[orientation] && @@ -2724,6 +2729,7 @@ gtk_stack_init (GtkStack *stack) priv->homogeneous[GTK_ORIENTATION_HORIZONTAL] = TRUE; priv->transition_duration = 200; priv->transition_type = GTK_STACK_TRANSITION_TYPE_NONE; + priv->children = g_ptr_array_new(); } /** @@ -2905,14 +2911,14 @@ gtk_stack_page_set_name (GtkStackPage *self, gtk_widget_get_parent (self->widget) && GTK_IS_STACK (gtk_widget_get_parent (self->widget))) { - GList *l; + guint idx; stack = GTK_STACK (gtk_widget_get_parent (self->widget)); priv = gtk_stack_get_instance_private (stack); - for (l = priv->children; l != NULL; l = l->next) + for (idx = 0; idx < priv->children->len; idx++) { - GtkStackPage *info2 = l->data; + GtkStackPage *info2 = g_ptr_array_index (priv->children, idx); if (self == info2) continue;