mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-04 04:00:17 +01:00
glib-aux: add nm_g_source_sentinel_get() util
This helper is useful to get a dummy GSource instance that can be refed, unrefed and destroyed. It can act as a replacement for a timeout source with infinite timeout.
This commit is contained in:
parent
a9776e7ed9
commit
ce7c28c514
3 changed files with 105 additions and 0 deletions
|
|
@ -4851,6 +4851,33 @@ nm_utils_parse_debug_string(const char *string, const GDebugKey *keys, guint nke
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
GSource *_nm_g_source_sentinel[] = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
GSource *
|
||||||
|
_nm_g_source_sentinel_get_init(GSource **p_source)
|
||||||
|
{
|
||||||
|
static const GSourceFuncs source_funcs = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
GSource *source;
|
||||||
|
|
||||||
|
again:
|
||||||
|
source = g_source_new((GSourceFuncs *) &source_funcs, sizeof(GSource));
|
||||||
|
g_source_set_priority(source, G_PRIORITY_DEFAULT_IDLE);
|
||||||
|
g_source_set_name(source, "nm_g_source_sentinel");
|
||||||
|
|
||||||
|
if (!g_atomic_pointer_compare_and_exchange(p_source, NULL, source)) {
|
||||||
|
g_source_unref(source);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
GSource *
|
GSource *
|
||||||
nm_g_idle_source_new(int priority,
|
nm_g_idle_source_new(int priority,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
|
|
|
||||||
|
|
@ -1594,6 +1594,31 @@ nm_source_func_unref_gobject(gpointer user_data)
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern GSource *_nm_g_source_sentinel[1];
|
||||||
|
|
||||||
|
GSource *_nm_g_source_sentinel_get_init(GSource **p_source);
|
||||||
|
|
||||||
|
/* Get a GSource sentinel (dummy instance). This instance should never be
|
||||||
|
* attached to a GMainContext. The only currently known purpose is to use it
|
||||||
|
* as dummy value instead of an infinity timeout. That is, if we configurably
|
||||||
|
* want to schedule a timeout that might be infinity, we might set the GSource
|
||||||
|
* instance to nm_g_source_sentinel_get(). On this instance, we still may
|
||||||
|
* call g_source_ref(), g_source_unref() and g_source_destroy(). But nothing
|
||||||
|
* else. */
|
||||||
|
#define nm_g_source_sentinel_get(idx) \
|
||||||
|
({ \
|
||||||
|
GSource *_s; \
|
||||||
|
\
|
||||||
|
G_STATIC_ASSERT((idx) >= 0); \
|
||||||
|
G_STATIC_ASSERT((idx) < G_N_ELEMENTS(_nm_g_source_sentinel)); \
|
||||||
|
\
|
||||||
|
_s = g_atomic_pointer_get(&_nm_g_source_sentinel[idx]); \
|
||||||
|
if (G_UNLIKELY(!_s)) \
|
||||||
|
_s = _nm_g_source_sentinel_get_init(&_nm_g_source_sentinel[idx]); \
|
||||||
|
\
|
||||||
|
_s; \
|
||||||
|
})
|
||||||
|
|
||||||
GSource *nm_g_idle_source_new(int priority,
|
GSource *nm_g_idle_source_new(int priority,
|
||||||
GSourceFunc func,
|
GSourceFunc func,
|
||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
|
|
|
||||||
|
|
@ -1293,6 +1293,58 @@ again:
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_nm_g_source_sentinel(void)
|
||||||
|
{
|
||||||
|
GSource *s1;
|
||||||
|
GSource *s2;
|
||||||
|
int n;
|
||||||
|
int i;
|
||||||
|
int refs;
|
||||||
|
|
||||||
|
s1 = nm_g_source_sentinel_get(0);
|
||||||
|
g_assert_nonnull(s1);
|
||||||
|
g_assert_cmpint(g_atomic_int_get(&s1->ref_count), ==, 1);
|
||||||
|
|
||||||
|
s2 = nm_g_source_sentinel_get(0);
|
||||||
|
g_assert_nonnull(s2);
|
||||||
|
g_assert(s2 == s1);
|
||||||
|
g_assert_cmpint(g_atomic_int_get(&s1->ref_count), ==, 1);
|
||||||
|
|
||||||
|
n = nmtst_get_rand_uint32() % 7;
|
||||||
|
for (refs = 0, i = 0; i < n; i++) {
|
||||||
|
if (nmtst_get_rand_bool()) {
|
||||||
|
refs++;
|
||||||
|
g_source_ref(s1);
|
||||||
|
}
|
||||||
|
if (nmtst_get_rand_bool())
|
||||||
|
g_source_destroy(s1);
|
||||||
|
if (refs > 0 && nmtst_get_rand_bool()) {
|
||||||
|
refs--;
|
||||||
|
g_source_unref(s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nmtst_get_rand_bool()) {
|
||||||
|
s2 = nm_g_source_sentinel_get(0);
|
||||||
|
g_assert(s2 == s1);
|
||||||
|
g_assert_cmpint(g_atomic_int_get(&s1->ref_count), >=, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; refs > 0;) {
|
||||||
|
if (nmtst_get_rand_bool())
|
||||||
|
g_source_destroy(s1);
|
||||||
|
if (nmtst_get_rand_bool()) {
|
||||||
|
refs--;
|
||||||
|
g_source_unref(s1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_cmpint(g_atomic_int_get(&s1->ref_count), ==, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
NMTST_DEFINE();
|
NMTST_DEFINE();
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -1323,6 +1375,7 @@ main(int argc, char **argv)
|
||||||
g_test_add_func("/general/test_is_specific_hostname", test_is_specific_hostname);
|
g_test_add_func("/general/test_is_specific_hostname", test_is_specific_hostname);
|
||||||
g_test_add_func("/general/test_strv_dup_packed", test_strv_dup_packed);
|
g_test_add_func("/general/test_strv_dup_packed", test_strv_dup_packed);
|
||||||
g_test_add_func("/general/test_utils_hashtable_cmp", test_utils_hashtable_cmp);
|
g_test_add_func("/general/test_utils_hashtable_cmp", test_utils_hashtable_cmp);
|
||||||
|
g_test_add_func("/general/test_nm_g_source_sentinel", test_nm_g_source_sentinel);
|
||||||
|
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue