mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-26 14:40:08 +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 *
|
||||
nm_g_idle_source_new(int priority,
|
||||
GSourceFunc func,
|
||||
|
|
|
|||
|
|
@ -1594,6 +1594,31 @@ nm_source_func_unref_gobject(gpointer user_data)
|
|||
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,
|
||||
GSourceFunc func,
|
||||
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();
|
||||
|
||||
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_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_nm_g_source_sentinel", test_nm_g_source_sentinel);
|
||||
|
||||
return g_test_run();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue