From d100ce28e09273205f3443286f9c582702c1db67 Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 15 Aug 2017 12:32:37 +0200 Subject: [PATCH] shared: add nm_g_slice_free_fcn() util Useful, when you need a GDestroyNotify function for g_slice_free() of a certain type. --- libnm-core/tests/test-general.c | 21 ++++++++++++++ shared/nm-utils/nm-shared-utils.h | 47 +++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 20b27de9f5..00ac2cebe5 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -78,6 +78,26 @@ G_STATIC_ASSERT (sizeof (bool) <= sizeof (int)); /*****************************************************************************/ +static void +test_nm_g_slice_free_fcn (void) +{ + gpointer p; + + p = g_slice_new (gint64); + (nm_g_slice_free_fcn (gint64)) (p); + + p = g_slice_new (gint32); + (nm_g_slice_free_fcn (gint32)) (p); + + p = g_slice_new (gint); + (nm_g_slice_free_fcn (gint)) (p); + + p = g_slice_new (gint64); + nm_g_slice_free_fcn_gint64 (p); +} + +/*****************************************************************************/ + typedef struct { int val; int idx; @@ -6177,6 +6197,7 @@ int main (int argc, char **argv) { nmtst_init (&argc, &argv, TRUE); + g_test_add_func ("/core/general/test_nm_g_slice_free_fcn", test_nm_g_slice_free_fcn); g_test_add_func ("/core/general/test_c_list_sort", test_c_list_sort); g_test_add_func ("/core/general/test_dedup_multi", test_dedup_multi); g_test_add_func ("/core/general/test_utils_str_utf8safe", test_utils_str_utf8safe); diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index c4306f4120..6c8eb4dac2 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -150,6 +150,53 @@ gint _nm_utils_ascii_str_to_bool (const char *str, /*****************************************************************************/ +#define _nm_g_slice_free_fcn_define(mem_size) \ +static inline void \ +_nm_g_slice_free_fcn_##mem_size (gpointer mem_block) \ +{ \ + g_slice_free1 (mem_size, mem_block); \ +} + +_nm_g_slice_free_fcn_define (1) +_nm_g_slice_free_fcn_define (2) +_nm_g_slice_free_fcn_define (4) +_nm_g_slice_free_fcn_define (8) +_nm_g_slice_free_fcn_define (16) + +#define _nm_g_slice_free_fcn1(mem_size) \ + ({ \ + void (*_fcn) (gpointer); \ + \ + /* If mem_size is a compile time constant, the compiler + * will be able to optimize this. Hence, you don't want + * to call this with a non-constant size argument. */ \ + switch (mem_size) { \ + case 1: _fcn = _nm_g_slice_free_fcn_1; break; \ + case 2: _fcn = _nm_g_slice_free_fcn_2; break; \ + case 4: _fcn = _nm_g_slice_free_fcn_4; break; \ + case 8: _fcn = _nm_g_slice_free_fcn_8; break; \ + case 16: _fcn = _nm_g_slice_free_fcn_16; break; \ + default: g_assert_not_reached (); _fcn = NULL; break; \ + } \ + _fcn; \ + }) + +/** + * nm_g_slice_free_fcn: + * @type: type argument for sizeof() operator that you would + * pass to g_slice_new(). + * + * Returns: a function pointer with GDestroyNotify signature + * for g_slice_free(type,*). + * + * Only certain types are implemented. You'll get an assertion + * using the wrong type. */ +#define nm_g_slice_free_fcn(type) (_nm_g_slice_free_fcn1 (sizeof (type))) + +#define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn (gint64)) + +/*****************************************************************************/ + /** * NMUtilsError: * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error