gdataset: use hash lookup in g_datalist_get_data()

g_datalist_get_data() tries to avoid g_quark_try_string() and instead
do the lock-less g_quark_to_string(). For small number of entries that
may perform better. At least, this was an optimization from the past.

However, if we have a GHashTable index, and presumably a larger number
of entries, we should use the index instead. Unfortunately, that requires
us again to use g_quark_try_string() and take a global lock.
This commit is contained in:
Thomas Haller 2024-02-06 08:48:32 +01:00
parent 0746df4906
commit 9abc4d9be6

View File

@ -1423,37 +1423,56 @@ g_datalist_id_replace_data (GData **datalist,
* is not found. * is not found.
**/ **/
gpointer gpointer
g_datalist_get_data (GData **datalist, g_datalist_get_data (GData **datalist,
const gchar *key) const gchar *key)
{ {
GQuark key_id;
GHashTable *index;
gpointer res = NULL; gpointer res = NULL;
GDataElt *data_elt;
GData *d; GData *d;
GDataElt *data, *data_end;
g_return_val_if_fail (datalist != NULL, NULL); g_return_val_if_fail (datalist != NULL, NULL);
d = g_datalist_lock_and_get (datalist); d = g_datalist_lock_and_get (datalist);
if (d)
if (!d)
goto out;
index = datalist_index_get (d);
if (G_LIKELY (!index))
{ {
data = d->data; guint32 i;
data_end = data + d->len;
while (data < data_end) for (i = 0; i < d->len; i++)
{ {
/* Here we intentionally compare by strings, instead of calling data_elt = &d->data[i];
* g_quark_try_string() first. /* Here we intentionally compare by strings, instead of calling
* * g_quark_try_string() first.
* See commit 1cceda49b60b ('Make g_datalist_get_data not look up the *
* quark'). * See commit 1cceda49b60b ('Make g_datalist_get_data not look up the
*/ * quark').
if (g_strcmp0 (g_quark_to_string (data->key), key) == 0) */
{ if (g_strcmp0 (g_quark_to_string (data_elt->key), key) == 0)
res = data->data; {
break; res = data_elt->data;
} goto out;
data++; }
} }
goto out;
} }
key_id = g_quark_try_string (key);
if (key_id == 0 && key)
goto out;
data_elt = g_hash_table_lookup (index, &key_id);
if (data_elt)
res = data_elt->data;
out:
g_datalist_unlock (datalist); g_datalist_unlock (datalist);
return res; return res;