[glib/finalize-speedups: 1/4] Add g_datalist_id_remove_multiple
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/finalize-speedups: 1/4] Add g_datalist_id_remove_multiple
- Date: Mon, 23 May 2022 10:15:01 +0000 (UTC)
commit a50e4bb15d03f0310d38c84ac1f69d6e059506e2
Author: Matthias Clasen <mclasen redhat com>
Date: Sun May 22 06:47:55 2022 -0400
Add g_datalist_id_remove_multiple
This is more efficient than calling
g_datalist_id_remove() multiple times
in a row, since it only takes the locks
once.
Allow up to 16 keys to be removed in one go.
That is enough for the use we have in GObject,
and it avoids any danger of blowing the stack.
docs/reference/glib/glib-sections.txt | 1 +
glib/gdataset.c | 103 ++++++++++++++++++++++++++++++++++
glib/gdataset.h | 4 ++
3 files changed, 108 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 2932313cd0..bacf386840 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -3220,6 +3220,7 @@ g_datalist_id_set_data_full
g_datalist_id_get_data
g_datalist_id_remove_data
g_datalist_id_remove_no_notify
+g_datalist_id_remove_multiple
GDuplicateFunc
g_datalist_id_dup_data
g_datalist_id_replace_data
diff --git a/glib/gdataset.c b/glib/gdataset.c
index 758c032ab3..8b3649b23a 100644
--- a/glib/gdataset.c
+++ b/glib/gdataset.c
@@ -46,6 +46,7 @@
#include "gtestutils.h"
#include "gthread.h"
#include "glib_trace.h"
+#include "galloca.h"
/**
* SECTION:datasets
@@ -487,6 +488,85 @@ g_data_set_internal (GData **datalist,
}
+static inline void
+g_data_remove_internal (GData **datalist,
+ GQuark *keys,
+ gsize n_keys)
+{
+ GData *d;
+
+ g_datalist_lock (datalist);
+
+ d = G_DATALIST_GET_POINTER (datalist);
+
+ if (d)
+ {
+ GDataElt *old, *data, *data_end;
+ gsize found_keys;
+
+ old = g_newa (GDataElt, n_keys);
+
+ data = d->data;
+ data_end = data + d->len;
+ found_keys = 0;
+
+ while (data < data_end && found_keys < n_keys)
+ {
+ gboolean remove = FALSE;
+
+ for (gsize i = 0; i < n_keys; i++)
+ {
+ if (data->key == keys[i])
+ {
+ remove = TRUE;
+ break;
+ }
+ }
+
+ if (remove)
+ {
+ old[found_keys] = *data;
+ found_keys++;
+
+ if (data < data_end)
+ {
+ data_end--;
+ *data = *data_end;
+ }
+
+ d->len--;
+
+ /* We don't bother to shrink, but if all data are now gone
+ * we at least free the memory
+ */
+ if (d->len == 0)
+ {
+ G_DATALIST_SET_POINTER (datalist, NULL);
+ g_free (d);
+ break;
+ }
+ }
+
+ data++;
+ }
+
+ if (found_keys > 0)
+ {
+ g_datalist_unlock (datalist);
+
+ for (gsize i = 0; i < found_keys; i++)
+ {
+ if (old[i].destroy)
+ old[i].destroy (old[i].data);
+ }
+
+ return;
+ }
+ }
+
+ g_datalist_unlock (datalist);
+}
+
/**
* g_dataset_id_set_data_full: (skip)
* @dataset_location: (not nullable): the location identifying the dataset.
@@ -672,6 +752,29 @@ g_datalist_id_set_data_full (GData **datalist,
g_data_set_internal (datalist, key_id, data, destroy_func, NULL);
}
+/**
+ * g_datalist_id_remove_multiple:
+ * @datalist: a datalist
+ * @keys: (array length=n_keys): keys to remove
+ * @n_keys: length of @keys, must be <= 16
+ *
+ * Removes multiple keys from a datalist.
+ *
+ * This is more efficient than calling g_datalist_id_remove()
+ * multiple times in a row.
+ *
+ * Since: 2.74
+ */
+void
+g_datalist_id_remove_multiple (GData **datalist,
+ GQuark *keys,
+ guint n_keys)
+{
+ g_return_if_fail (n_keys <= 16);
+
+ g_data_remove_internal (datalist, keys, n_keys);
+}
+
/**
* g_dataset_id_remove_no_notify: (skip)
* @dataset_location: (not nullable): the location identifying the dataset.
diff --git a/glib/gdataset.h b/glib/gdataset.h
index a85179c60d..f9731c6cb5 100644
--- a/glib/gdataset.h
+++ b/glib/gdataset.h
@@ -55,6 +55,10 @@ void g_datalist_id_set_data_full (GData **datalist,
GQuark key_id,
gpointer data,
GDestroyNotify destroy_func);
+GLIB_AVAILABLE_IN_2_74
+void g_datalist_id_remove_multiple (GData **datalist,
+ GQuark *keys,
+ guint n_keys);
typedef gpointer (*GDuplicateFunc) (gpointer data, gpointer user_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]