gdataset: update pointers at end of g_datalist_id_replace_data()

- when setting datalist to NULL, do it at the end with
  g_datalist_unlock_and_set() to avoid the additional atomic
  operations.
- when freeing the old "d", do that after releasing the bit
  lock.
This commit is contained in:
Thomas Haller 2024-01-05 12:34:50 +01:00
parent a426410919
commit 435aa01158

View File

@ -963,6 +963,8 @@ g_datalist_id_replace_data (GData **datalist,
GData *d; GData *d;
GData *new_d = NULL; GData *new_d = NULL;
GDataElt *data, *data_end; GDataElt *data, *data_end;
gboolean free_d = FALSE;
gboolean set_new_d = FALSE;
g_return_val_if_fail (datalist != NULL, FALSE); g_return_val_if_fail (datalist != NULL, FALSE);
g_return_val_if_fail (key_id != 0, FALSE); g_return_val_if_fail (key_id != 0, FALSE);
@ -1002,8 +1004,8 @@ g_datalist_id_replace_data (GData **datalist,
*/ */
if (d->len == 0) if (d->len == 0)
{ {
G_DATALIST_SET_POINTER (datalist, NULL); set_new_d = TRUE;
g_free (d); free_d = TRUE;
} }
} }
} }
@ -1031,7 +1033,10 @@ g_datalist_id_replace_data (GData **datalist,
d = g_realloc (d, sizeof (GData) + (d->alloc - 1) * sizeof (GDataElt)); d = g_realloc (d, sizeof (GData) + (d->alloc - 1) * sizeof (GDataElt));
} }
if (old_d != d) if (old_d != d)
new_d = d; {
new_d = d;
set_new_d = TRUE;
}
d->data[d->len].key = key_id; d->data[d->len].key = key_id;
d->data[d->len].data = newval; d->data[d->len].data = newval;
@ -1039,11 +1044,14 @@ g_datalist_id_replace_data (GData **datalist,
d->len++; d->len++;
} }
if (new_d) if (set_new_d)
g_datalist_unlock_and_set (datalist, new_d); g_datalist_unlock_and_set (datalist, new_d);
else else
g_datalist_unlock (datalist); g_datalist_unlock (datalist);
if (free_d)
g_free (d);
return val == oldval; return val == oldval;
} }