[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 13:20:22 +0000 (UTC)
commit 0415bf94127c692094facaba6ef349e6809617e4
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..6b78d2e33f 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_data()
+ * multiple times in a row.
+ *
+ * Since: 2.74
+ */
+void
+g_datalist_id_remove_multiple (GData **datalist,
+ GQuark *keys,
+ gsize 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..a0d44b09ec 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,
+ gsize n_keys);
typedef gpointer (*GDuplicateFunc) (gpointer data, gpointer user_data);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]