/* ---------------------------------------------------------------------------------------------------- */
+typedef struct
+{
+ GDestroyNotify callback;
+ gpointer user_data;
+ GMainContext *context;
+} CallDestroyNotifyData;
+
+static gboolean
+call_destroy_notify_data_in_idle (gpointer user_data)
+{
+ CallDestroyNotifyData *data = user_data;
+ data->callback (data->user_data);
+ return FALSE;
+}
+
+static void
+call_destroy_notify_data_free (CallDestroyNotifyData *data)
+{
+ if (data->context != NULL)
+ g_main_context_unref (data->context);
+ g_free (data);
+}
+
+/*
+ * call_destroy_notify: <internal>
+ * @context: A #GMainContext or %NULL.
+ * @callback: A #GDestroyNotify or %NULL.
+ * @user_data: Data to pass to @callback.
+ *
+ * Schedules @callback to run in @context.
+ */
+static void
+call_destroy_notify (GMainContext *context,
+ GDestroyNotify callback,
+ gpointer user_data)
+{
+ if (callback == NULL)
+ goto out;
+
+ if (context == g_main_context_get_thread_default ())
+ {
+ callback (user_data);
+ }
+ else
+ {
+ GSource *idle_source;
+ CallDestroyNotifyData *data;
+
+ data = g_new0 (CallDestroyNotifyData, 1);
+ data->callback = callback;
+ data->user_data = user_data;
+ data->context = context;
+ if (data->context != NULL)
+ g_main_context_ref (data->context);
+
+ idle_source = g_idle_source_new ();
+ g_source_set_priority (idle_source, G_PRIORITY_DEFAULT);
+ g_source_set_callback (idle_source,
+ call_destroy_notify_data_in_idle,
+ data,
+ (GDestroyNotify) call_destroy_notify_data_free);
+ g_source_attach (idle_source, data->context);
+ g_source_unref (idle_source);
+ }
+
+ out:
+ ;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static gboolean
_g_strv_has_string (const gchar* const *haystack,
const gchar *needle)
{
SignalSubscriber *subscriber;
subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
- if (subscriber->user_data_free_func != NULL)
- subscriber->user_data_free_func (subscriber->user_data);
+ call_destroy_notify (subscriber->context,
+ subscriber->user_data_free_func,
+ subscriber->user_data);
if (subscriber->context != NULL)
g_main_context_unref (subscriber->context);
}
{
SignalSubscriber *subscriber;
subscriber = &(g_array_index (subscribers, SignalSubscriber, n));
- if (subscriber->user_data_free_func != NULL)
- subscriber->user_data_free_func (subscriber->user_data);
+ call_destroy_notify (subscriber->context,
+ subscriber->user_data_free_func,
+ subscriber->user_data);
if (subscriber->context != NULL)
g_main_context_unref (subscriber->context);
}
{
g_dbus_interface_info_unref ((GDBusInterfaceInfo *) ei->interface_info);
- if (ei->user_data_free_func != NULL)
- /* TODO: push to thread-default mainloop */
- ei->user_data_free_func (ei->user_data);
+ call_destroy_notify (ei->context,
+ ei->user_data_free_func,
+ ei->user_data);
if (ei->context != NULL)
g_main_context_unref (ei->context);
static void
exported_subtree_free (ExportedSubtree *es)
{
- if (es->user_data_free_func != NULL)
- /* TODO: push to thread-default mainloop */
- es->user_data_free_func (es->user_data);
+ call_destroy_notify (es->context,
+ es->user_data_free_func,
+ es->user_data);
if (es->context != NULL)
g_main_context_unref (es->context);
/* all tests rely on a shared mainloop */
static GMainLoop *loop = NULL;
+G_GNUC_UNUSED static void
+_log (const gchar *format, ...)
+{
+ GTimeVal now;
+ time_t now_time;
+ struct tm *now_tm;
+ gchar time_buf[128];
+ gchar *str;
+ va_list var_args;
+
+ va_start (var_args, format);
+ str = g_strdup_vprintf (format, var_args);
+ va_end (var_args);
+
+ g_get_current_time (&now);
+ now_time = (time_t) now.tv_sec;
+ now_tm = localtime (&now_time);
+ strftime (time_buf, sizeof time_buf, "%H:%M:%S", now_tm);
+
+ g_print ("%s.%06d: %s\n",
+ time_buf, (gint) now.tv_usec / 1000,
+ str);
+ g_free (str);
+}
+
static gboolean
test_connection_quit_mainloop (gpointer user_data)
{
- gboolean *quit_mainloop_fired = user_data;
+ volatile gboolean *quit_mainloop_fired = user_data;
+ //_log ("quit_mainloop_fired");
*quit_mainloop_fired = TRUE;
g_main_loop_quit (loop);
return TRUE;
static void
a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop (gpointer user_data)
{
- gboolean *val = user_data;
+ volatile gboolean *val = user_data;
*val = TRUE;
-
+ //_log ("destroynotify fired for %p", val);
g_main_loop_quit (loop);
}
GDBusConnection *c;
GDBusConnection *c2;
GError *error;
- gboolean on_signal_registration_freed_called;
- gboolean on_filter_freed_called;
- gboolean on_register_object_freed_called;
- gboolean quit_mainloop_fired;
+ volatile gboolean on_signal_registration_freed_called;
+ volatile gboolean on_filter_freed_called;
+ volatile gboolean on_register_object_freed_called;
+ volatile gboolean quit_mainloop_fired;
guint quit_mainloop_id;
guint registration_id;
NULL, /* arg0 */
G_DBUS_SIGNAL_FLAGS_NONE,
on_name_owner_changed,
- &on_signal_registration_freed_called,
+ (gpointer) &on_signal_registration_freed_called,
a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop);
/* filter func */
on_filter_freed_called = FALSE;
g_dbus_connection_add_filter (c2,
some_filter_func,
- &on_filter_freed_called,
+ (gpointer) &on_filter_freed_called,
a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop);
/* object registration */
on_register_object_freed_called = FALSE;
"/foo",
(GDBusInterfaceInfo *) &boo_interface_info,
&boo_vtable,
- &on_register_object_freed_called,
+ (gpointer) &on_register_object_freed_called,
a_gdestroynotify_that_sets_a_gboolean_to_true_and_quits_loop,
&error);
g_assert_no_error (error);
/* ok, finalize the connection and check that all the GDestroyNotify functions are invoked as expected */
g_object_unref (c2);
quit_mainloop_fired = FALSE;
- quit_mainloop_id = g_timeout_add (30000, test_connection_quit_mainloop, &quit_mainloop_fired);
+ quit_mainloop_id = g_timeout_add (30000, test_connection_quit_mainloop, (gpointer) &quit_mainloop_fired);
+ //_log ("destroynotifies for\n"
+ // " register_object %p\n"
+ // " filter %p\n"
+ // " signal %p",
+ // &on_register_object_freed_called,
+ // &on_filter_freed_called,
+ // &on_signal_registration_freed_called);
while (TRUE)
{
if (on_signal_registration_freed_called &&
break;
if (quit_mainloop_fired)
break;
+ //_log ("entering loop");
g_main_loop_run (loop);
+ //_log ("exiting loop");
}
g_source_remove (quit_mainloop_id);
g_assert (on_signal_registration_freed_called);