mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-09 18:30:08 +00:00
listlistmodel: Add a cache
Cache the last looked up item and use it for looking up the next item if it's closest. This massively speeds up iteration over the model, because each call to get_item() will be adjacent to the previous one. Improves performance of the inspector quite a bit.
This commit is contained in:
parent
41454b63b4
commit
e010cd242c
@ -41,6 +41,9 @@ struct _GtkListListModel
|
||||
gpointer (* get_item) (gpointer, gpointer);
|
||||
gpointer data;
|
||||
GDestroyNotify notify;
|
||||
|
||||
guint cache_pos;
|
||||
gpointer cache_item;
|
||||
};
|
||||
|
||||
struct _GtkListListModelClass
|
||||
@ -72,6 +75,18 @@ gtk_list_list_model_get_n_items (GListModel *list)
|
||||
return self->n_items;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_list_list_model_cache_is_valid (GtkListListModel *self)
|
||||
{
|
||||
return self->cache_item != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_list_list_model_invalidate_cache (GtkListListModel *self)
|
||||
{
|
||||
self->cache_item = NULL;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
gtk_list_list_model_get_item (GListModel *list,
|
||||
guint position)
|
||||
@ -79,31 +94,50 @@ gtk_list_list_model_get_item (GListModel *list,
|
||||
GtkListListModel *self = GTK_LIST_LIST_MODEL (list);
|
||||
gpointer result;
|
||||
guint i;
|
||||
guint start, end;
|
||||
|
||||
if (position >= self->n_items)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if (self->get_last &&
|
||||
position >= self->n_items / 2)
|
||||
{
|
||||
result = self->get_last (self->data);
|
||||
return NULL;
|
||||
|
||||
for (i = self->n_items - 1; i > position; i--)
|
||||
start = 0;
|
||||
end = self->n_items;
|
||||
if (gtk_list_list_model_cache_is_valid (self))
|
||||
{
|
||||
if (self->cache_pos <= position)
|
||||
start = self->cache_pos;
|
||||
else
|
||||
end = self->cache_pos;
|
||||
}
|
||||
|
||||
if (self->get_last &&
|
||||
position > (start + end) / 2)
|
||||
{
|
||||
if (end == self->cache_pos && gtk_list_list_model_cache_is_valid (self))
|
||||
result = self->get_previous (self->cache_item, self->data);
|
||||
else
|
||||
result = self->get_last (self->data);
|
||||
|
||||
for (i = end - 1; i > position; i--)
|
||||
{
|
||||
result = self->get_previous (result, self->data);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = self->get_first (self->data);
|
||||
if (start == self->cache_pos && gtk_list_list_model_cache_is_valid (self))
|
||||
result = self->cache_item;
|
||||
else
|
||||
result = self->get_first (self->data);
|
||||
|
||||
for (i = 0; i < position; i++)
|
||||
for (i = start; i < position; i++)
|
||||
{
|
||||
result = self->get_next (result, self->data);
|
||||
}
|
||||
}
|
||||
|
||||
self->cache_item = result;
|
||||
self->cache_pos = position;
|
||||
|
||||
return self->get_item (result, self->data);
|
||||
}
|
||||
|
||||
@ -275,7 +309,9 @@ gtk_list_list_model_item_added_at (GtkListListModel *self,
|
||||
g_return_if_fail (GTK_IS_LIST_LIST_MODEL (self));
|
||||
g_return_if_fail (position <= self->n_items);
|
||||
|
||||
self->n_items += 1;
|
||||
self->n_items++;
|
||||
if (position <= self->cache_pos)
|
||||
self->cache_pos++;
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
|
||||
@ -327,6 +363,12 @@ gtk_list_list_model_item_moved (GtkListListModel *self,
|
||||
|
||||
min = MIN (position, previous_position);
|
||||
max = MAX (position, previous_position) + 1;
|
||||
|
||||
if (self->cache_item == item)
|
||||
self->cache_pos = position;
|
||||
else if (self->cache_pos >= min && self->cache_pos < max)
|
||||
self->cache_pos += (self->cache_pos > position ? 1 : -1);
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), min, max - min, max - min);
|
||||
}
|
||||
|
||||
@ -338,6 +380,10 @@ gtk_list_list_model_item_removed_at (GtkListListModel *self,
|
||||
g_return_if_fail (position < self->n_items);
|
||||
|
||||
self->n_items -= 1;
|
||||
if (position == self->cache_pos)
|
||||
gtk_list_list_model_invalidate_cache (self);
|
||||
else if (position < self->cache_pos)
|
||||
self->cache_pos--;
|
||||
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_N_ITEMS]);
|
||||
@ -358,6 +404,8 @@ gtk_list_list_model_clear (GtkListListModel *self)
|
||||
self->n_items = 0;
|
||||
self->notify = NULL;
|
||||
|
||||
gtk_list_list_model_invalidate_cache (self);
|
||||
|
||||
if (n_items > 0)
|
||||
{
|
||||
g_list_model_items_changed (G_LIST_MODEL (self), 0, n_items, 0);
|
||||
|
Loading…
Reference in New Issue
Block a user