[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: Sun, 22 May 2022 12:38:17 +0000 (UTC)
commit 6c78040371ca92f492ad145b9b8d4bf86156b04b
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.
docs/reference/glib/glib-sections.txt | 1 +
glib/gdataset.c | 101 ++++++++++++++++++++++++++++++++++
glib/gdataset.h | 4 ++
3 files changed, 106 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..2038d5b659 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,
+ guint n_keys)
+{
+ GData *d;
+
+ g_datalist_lock (datalist);
+
+ d = G_DATALIST_GET_POINTER (datalist);
+
+ if (d)
+ {
+ GDataElt *old, *data, *data_end;
+ guint 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 (guint 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 (guint 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,27 @@ 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: keys to remove
+ * @n_keys: length of @keys
+ *
+ * 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_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]