summaryrefslogtreecommitdiff
path: root/src/libnmc-setting/nm-meta-setting-base-impl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnmc-setting/nm-meta-setting-base-impl.c')
-rw-r--r--src/libnmc-setting/nm-meta-setting-base-impl.c81
1 files changed, 77 insertions, 4 deletions
diff --git a/src/libnmc-setting/nm-meta-setting-base-impl.c b/src/libnmc-setting/nm-meta-setting-base-impl.c
index 31e1012b1d..5e627cfc7d 100644
--- a/src/libnmc-setting/nm-meta-setting-base-impl.c
+++ b/src/libnmc-setting/nm-meta-setting-base-impl.c
@@ -3,6 +3,8 @@
* Copyright (C) 2017 - 2018 Red Hat, Inc.
*/
+#define NM_WANT_NM_ARRAY_FIND_BSEARCH_INLINE
+
#include "libnm-glib-aux/nm-default-glib-i18n-lib.h"
#include "nm-meta-setting-base.h"
@@ -745,6 +747,75 @@ _infos_by_gtype_search(GType gtype)
return NULL;
}
+typedef struct {
+ GType gtype;
+ const NMMetaSettingInfo *setting_info;
+} LookupData;
+
+_nm_always_inline static inline int
+_lookup_data_cmp(gconstpointer ptr_a, gconstpointer ptr_b, gpointer user_data)
+{
+ const GType *const a = ptr_a;
+ const GType *const b = ptr_b;
+
+ nm_assert(a);
+ nm_assert(b);
+ nm_assert(a != b);
+
+ NM_CMP_DIRECT(*a, *b);
+ return 0;
+}
+
+static const NMMetaSettingInfo *
+_infos_by_gtype_binary_search(GType gtype)
+{
+ static LookupData static_array[_NM_META_SETTING_TYPE_NUM];
+ static const LookupData *static_ptr = NULL;
+ const LookupData *ptr;
+ gssize idx;
+
+again:
+ ptr = g_atomic_pointer_get(&static_ptr);
+ if (G_UNLIKELY(!ptr)) {
+ static gsize g_lock = 0;
+ int i;
+
+ if (!g_once_init_enter(&g_lock))
+ goto again;
+
+ for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
+ const NMMetaSettingInfo *m = &nm_meta_setting_infos[i];
+
+ static_array[i] = (LookupData){
+ .gtype = m->get_setting_gtype(),
+ .setting_info = m,
+ };
+ }
+
+ g_qsort_with_data(static_array,
+ _NM_META_SETTING_TYPE_NUM,
+ sizeof(static_array[0]),
+ _lookup_data_cmp,
+ NULL);
+
+ ptr = static_array;
+ g_atomic_pointer_set(&static_ptr, ptr);
+
+ g_once_init_leave(&g_lock, 1);
+ }
+
+ idx = nm_array_find_bsearch_inline(ptr,
+ _NM_META_SETTING_TYPE_NUM,
+ sizeof(ptr[0]),
+ &gtype,
+ _lookup_data_cmp,
+ NULL);
+ if (idx < 0)
+ return NULL;
+
+ return ptr[idx].setting_info;
+}
+
const NMMetaSettingInfo *
nm_meta_setting_infos_by_gtype(GType gtype)
{
@@ -752,13 +823,15 @@ nm_meta_setting_infos_by_gtype(GType gtype)
#if _NM_META_SETTING_BASE_IMPL_LIBNM
setting_info = _infos_by_gtype_from_class(gtype);
-
- if (NM_MORE_ASSERTS > 20)
- nm_assert(setting_info == _infos_by_gtype_search(gtype));
#else
- setting_info = _infos_by_gtype_search(gtype);
+ setting_info = _infos_by_gtype_binary_search(gtype);
#endif
+ if (NM_MORE_ASSERTS > 20) {
+ nm_assert(setting_info == _infos_by_gtype_search(gtype));
+ nm_assert(setting_info == _infos_by_gtype_binary_search(gtype));
+ }
+
return setting_info;
}