gdataset: use lookup index in g_datalist_id_remove_multiple()

In order to reuse datalist_find(), we turn the loops around. First loop
over the keys, and then (internally in datalist_find()) loop over the
entries.
This commit is contained in:
Thomas Haller 2024-02-06 09:13:51 +01:00
parent af4a43b064
commit 3437414dd4

View File

@ -723,7 +723,9 @@ g_data_remove_internal (GData **datalist,
GData *d_to_free; GData *d_to_free;
gsize found_keys; gsize found_keys;
gsize i_keys; gsize i_keys;
guint32 i_data;
if (n_keys == 0)
return;
d = g_datalist_lock_and_get (datalist); d = g_datalist_lock_and_get (datalist);
@ -749,33 +751,23 @@ g_data_remove_internal (GData **datalist,
old = old_to_free; old = old_to_free;
} }
i_data = 0;
found_keys = 0; found_keys = 0;
while (i_data < d->len && found_keys < n_keys)
{
GDataElt *data = &d->data[i_data];
gboolean remove = FALSE;
for (i_keys = 0; i_keys < n_keys; i_keys++) for (i_keys = 0; i_keys < n_keys; i_keys++)
{ {
if (data->key == keys[i_keys]) GDataElt *data_elt;
{ guint32 idx;
/* We must invoke the destroy notifications in the order of @keys.
* Hence, build up the list @old at index @i_keys. */
old[i_keys] = *data;
found_keys++;
remove = TRUE;
break;
}
}
if (!remove) data_elt = datalist_find (d, keys[i_keys], &idx);
{ if (!data_elt)
i_data++;
continue; continue;
}
datalist_remove (d, i_data); /* We must destroy the keys in the order in which they are specified.
* We achieve that here.
*
* Note that even if @keys contains duplicates, we correctly only
* find them once, as we remove the found entry right away. */
old[found_keys++] = *data_elt;
datalist_remove (d, idx);
} }
if (found_keys > 0 && datalist_shrink (&d, &d_to_free)) if (found_keys > 0 && datalist_shrink (&d, &d_to_free))
@ -787,14 +779,11 @@ g_data_remove_internal (GData **datalist,
else else
g_datalist_unlock (datalist); g_datalist_unlock (datalist);
if (found_keys > 0) for (i_keys = 0; i_keys < found_keys; i_keys++)
{
for (i_keys = 0; i_keys < n_keys; i_keys++)
{ {
if (old[i_keys].destroy) if (old[i_keys].destroy)
old[i_keys].destroy (old[i_keys].data); old[i_keys].destroy (old[i_keys].data);
} }
}
if (G_UNLIKELY (old_to_free)) if (G_UNLIKELY (old_to_free))
g_free (old_to_free); g_free (old_to_free);
@ -996,9 +985,8 @@ g_datalist_id_set_data_full (GData **datalist,
* This is more efficient than calling g_datalist_id_remove_data() * This is more efficient than calling g_datalist_id_remove_data()
* multiple times in a row. * multiple times in a row.
* *
* Before 2.80, @n_keys had to be not larger than 16. Now it can be larger, but * Before 2.80, @n_keys had to be not larger than 16.
* note that GData does a linear search, so an excessive number of keys will * Since 2.84, performance is improved for larger number of keys.
* perform badly.
* *
* Since: 2.74 * Since: 2.74
*/ */