/** * dbus_server_setup_with_g_main: * @server: the server * @context: the #GMainContext or #NULL for default * * Sets the watch and timeout functions of a #DBusServer * to integrate the server with the GLib main loop. * In most cases the context argument should be #NULL. * * If called twice for the same context, does nothing the second * time. If called once with context A and once with context B, * context B replaces context A as the context monitoring the * connection. */ void dbus_server_setup (DBusServer *server, GMainContext *context) { ConnectionSetup *old_setup; ConnectionSetup *cs; do { /* FIXME we never free the slot, so its refcount just keeps growing, * which is kind of broken. */ dbus_server_allocate_data_slot (&server_slot); if (server_slot < 0) break; if (context == NULL) context = g_main_context_default (); cs = NULL; old_setup = dbus_server_get_data (server, server_slot); if (old_setup != NULL) { if (old_setup->context == context) return; /* nothing to do */ cs = connection_setup_new_from_old (context, old_setup); /* Nuke the old setup */ dbus_server_set_data (server, server_slot, NULL, NULL); old_setup = NULL; } if (cs == NULL) cs = connection_setup_new (context, NULL); if (!dbus_server_set_data (server, server_slot, cs, (DBusFreeFunction)connection_setup_free)) break; if (!dbus_server_set_watch_functions (server, add_watch, remove_watch, watch_toggled, cs, NULL)) break; if (!dbus_server_set_timeout_functions (server, add_timeout, remove_timeout, timeout_toggled, cs, NULL)) break; return; } while (0); g_error ("Not enough memory to set up DBusServer for use with GLib"); }
static dbus_bool_t setup_server (BusContext *context, DBusServer *server, char **auth_mechanisms, DBusError *error) { BusServerData *bd; bd = dbus_new0 (BusServerData, 1); if (bd == NULL || !dbus_server_set_data (server, server_data_slot, bd, free_server_data)) { dbus_free (bd); BUS_SET_OOM (error); return FALSE; } bd->context = context; if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms)) { BUS_SET_OOM (error); return FALSE; } dbus_server_set_new_connection_function (server, new_connection_callback, context, NULL); if (!dbus_server_set_watch_functions (server, add_server_watch, remove_server_watch, toggle_server_watch, server, NULL)) { BUS_SET_OOM (error); return FALSE; } if (!dbus_server_set_timeout_functions (server, add_server_timeout, remove_server_timeout, NULL, server, NULL)) { BUS_SET_OOM (error); return FALSE; } return TRUE; }
static void test_server (Fixture *f, gconstpointer data) { Thread public_api = { f, f->server, (RefFunc) dbus_server_ref, NULL, (VoidFunc) dbus_server_unref, NULL, NULL, NULL }; Thread internal_api = { f, f->server, NULL, (VoidFunc) _dbus_server_ref_unlocked, (VoidFunc) _dbus_server_unref_unlocked, f->server, server_lock, server_unlock }; unsigned i; if (!dbus_server_set_data (f->server, server_slot, f, last_unref)) g_error ("OOM"); for (i = 0; i < f->n_threads; i++) { if ((i % 2) == 0) f->threads[i] = g_thread_new (NULL, ref_thread, &public_api); else f->threads[i] = g_thread_new (NULL, ref_thread, &internal_api); g_assert (f->threads[i] != NULL); } wait_for_all_threads (f); for (i = 0; i < f->n_threads; i++) { if ((i % 2) == 0) f->threads[i] = g_thread_new (NULL, cycle_thread, &public_api); else f->threads[i] = g_thread_new (NULL, cycle_thread, &internal_api); g_assert (f->threads[i] != NULL); } wait_for_all_threads (f); for (i = 0; i < f->n_threads; i++) { if ((i % 2) == 0) f->threads[i] = g_thread_new (NULL, unref_thread, &public_api); else f->threads[i] = g_thread_new (NULL, unref_thread, &internal_api); g_assert (f->threads[i] != NULL); } wait_for_all_threads (f); /* Destroy the server. This should be the last-unref. */ g_assert (!f->last_unref); dbus_server_disconnect (f->server); dbus_server_unref (f->server); f->server = NULL; g_assert (f->last_unref); }