gdataset: cleanup g_data_remove_internal()

- only use gnewa0() for up to 400 bytes (arbitrarily chosen as
  something that is probably small enough to cover most small tasks
  while fitting easily on the stack). Otherwise fallback to g_new0().

- don't do intermediate G_DATALIST_SET_POINTER(). Set to NULL
  afterwards with g_datalist_unlock_and_set().

- move the g_free(d) after releasing the lock on datalist.
This commit is contained in:
Thomas Haller 2024-01-05 12:40:49 +01:00
parent 435aa01158
commit eada6be364

View File

@ -419,22 +419,38 @@ g_data_remove_internal (GData **datalist,
gsize n_keys)
{
GData *d;
GDataElt *old;
GDataElt *old_to_free = NULL;
GDataElt *data;
GDataElt *data_end;
gsize found_keys;
gboolean free_d = FALSE;
g_datalist_lock (datalist);
d = G_DATALIST_GET_POINTER (datalist);
if (d)
if (!d)
{
GDataElt *old, *data, *data_end;
gsize found_keys;
g_datalist_unlock (datalist);
return;
}
/* Allocate an array of GDataElt to hold copies of the elements
* that are removed from the datalist. Allow enough space for all
* the keys; if a key is not found, the corresponding element of
* old is not populated, so we initialize them all to NULL to
* detect that case. */
* detect that case.
*
* At most allocate 400 bytes on the stack. Especially since we call
* out to external code, we don't know how much stack we can use. */
if (n_keys <= 400u / sizeof (GDataElt))
old = g_newa0 (GDataElt, n_keys);
else
{
old_to_free = g_new0 (GDataElt, n_keys);
old = old_to_free;
}
data = d->data;
data_end = data + d->len;
@ -471,8 +487,7 @@ g_data_remove_internal (GData **datalist,
*/
if (d->len == 0)
{
G_DATALIST_SET_POINTER (datalist, NULL);
g_free (d);
free_d = TRUE;
break;
}
}
@ -482,10 +497,16 @@ g_data_remove_internal (GData **datalist,
}
}
if (found_keys > 0)
if (free_d)
{
g_datalist_unlock_and_set (datalist, NULL);
g_free (d);
}
else
g_datalist_unlock (datalist);
if (found_keys > 0)
{
for (gsize i = 0; i < n_keys; i++)
{
/* If keys[i] was not found, then old[i].destroy is NULL.
@ -494,12 +515,10 @@ g_data_remove_internal (GData **datalist,
if (old[i].destroy)
old[i].destroy (old[i].data);
}
return;
}
}
g_datalist_unlock (datalist);
if (G_UNLIKELY (old_to_free))
g_free (old_to_free);
}
/**