mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +01:00
gdataset: optimize return path in g_datalist_id_update_atomic()
The most common case is that the callback does not change the data/destroy pointers. Reorder the if checks to favor those cases. Also, avoid setting the data to the same value.
This commit is contained in:
parent
2d5a00707b
commit
357e611825
@ -1095,7 +1095,6 @@ g_datalist_id_update_atomic (GData **datalist,
|
|||||||
gpointer result;
|
gpointer result;
|
||||||
GDestroyNotify new_destroy;
|
GDestroyNotify new_destroy;
|
||||||
guint32 idx;
|
guint32 idx;
|
||||||
gboolean to_unlock = TRUE;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (already_locked))
|
if (G_UNLIKELY (already_locked))
|
||||||
{
|
{
|
||||||
@ -1121,49 +1120,59 @@ g_datalist_id_update_atomic (GData **datalist,
|
|||||||
|
|
||||||
result = callback (&new_data, &new_destroy, user_data);
|
result = callback (&new_data, &new_destroy, user_data);
|
||||||
|
|
||||||
if (data && !new_data)
|
if (data)
|
||||||
{
|
{
|
||||||
GData *d_to_free;
|
if (G_LIKELY (data->data == new_data && data->destroy == new_destroy))
|
||||||
|
|
||||||
/* Remove. The callback indicates to drop the entry.
|
|
||||||
*
|
|
||||||
* The old data->data was stolen by callback(). */
|
|
||||||
datalist_remove (d, idx);
|
|
||||||
if (datalist_shrink (&d, &d_to_free))
|
|
||||||
{
|
{
|
||||||
g_datalist_unlock_and_set (datalist, d);
|
/* No change. */
|
||||||
if (d_to_free)
|
}
|
||||||
g_free (d_to_free);
|
else if (!new_data)
|
||||||
to_unlock = FALSE;
|
{
|
||||||
|
GData *d_to_free;
|
||||||
|
|
||||||
|
/* Remove. The callback indicates to drop the entry.
|
||||||
|
*
|
||||||
|
* The old data->data was stolen by callback(). */
|
||||||
|
datalist_remove (d, idx);
|
||||||
|
if (datalist_shrink (&d, &d_to_free))
|
||||||
|
{
|
||||||
|
g_datalist_unlock_and_set (datalist, d);
|
||||||
|
if (d_to_free)
|
||||||
|
g_free (d_to_free);
|
||||||
|
goto return_without_unlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Update. The callback may have provided new pointers to an existing
|
||||||
|
* entry.
|
||||||
|
*
|
||||||
|
* The old data was stolen by callback(). We only update the pointers and
|
||||||
|
* are done. */
|
||||||
|
data->data = new_data;
|
||||||
|
data->destroy = new_destroy;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (data)
|
|
||||||
{
|
|
||||||
/* Update. The callback may have provided new pointers to an existing
|
|
||||||
* entry.
|
|
||||||
*
|
|
||||||
* The old data was stolen by callback(). We only update the pointers and
|
|
||||||
* are done. */
|
|
||||||
data->data = new_data;
|
|
||||||
data->destroy = new_destroy;
|
|
||||||
}
|
|
||||||
else if (!data && !new_data)
|
|
||||||
{
|
|
||||||
/* Absent. No change. The entry didn't exist and still does not. */
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Add. Add a new entry that didn't exist previously. */
|
if (G_LIKELY (!new_data))
|
||||||
if (datalist_append (&d, key_id, new_data, new_destroy))
|
|
||||||
{
|
{
|
||||||
g_datalist_unlock_and_set (datalist, d);
|
/* No change. The entry didn't exist and still does not. */
|
||||||
to_unlock = FALSE;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Add. Add a new entry that didn't exist previously. */
|
||||||
|
if (datalist_append (&d, key_id, new_data, new_destroy))
|
||||||
|
{
|
||||||
|
g_datalist_unlock_and_set (datalist, d);
|
||||||
|
goto return_without_unlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (to_unlock)
|
g_datalist_unlock (datalist);
|
||||||
g_datalist_unlock (datalist);
|
|
||||||
|
|
||||||
|
return_without_unlock:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user