*
*/
+#include <config.h>
#include "dbus-connection.h"
#include "dbus-list.h"
#include "dbus-timeout.h"
#include "dbus-protocol.h"
#include "dbus-dataslot.h"
+#if 1
+#define CONNECTION_LOCK(connection) do { \
+ _dbus_verbose (" LOCK: %s\n", _DBUS_FUNCTION_NAME); \
+ dbus_mutex_lock ((connection)->mutex); \
+ } while (0)
+#define CONNECTION_UNLOCK(connection) do { \
+ _dbus_verbose (" UNLOCK: %s\n", _DBUS_FUNCTION_NAME); \
+ dbus_mutex_unlock ((connection)->mutex); \
+ } while (0)
+#else
+#define CONNECTION_LOCK(connection) dbus_mutex_lock ((connection)->mutex)
+#define CONNECTION_UNLOCK(connection) dbus_mutex_unlock ((connection)->mutex)
+#endif
+
/**
* @defgroup DBusConnection DBusConnection
* @ingroup DBus
*/
struct DBusConnection
{
- int refcount; /**< Reference count. */
+ dbus_atomic_t refcount; /**< Reference count. */
DBusMutex *mutex; /**< Lock on the entire DBusConnection */
void
_dbus_connection_lock (DBusConnection *connection)
{
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
}
/**
void
_dbus_connection_unlock (DBusConnection *connection)
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
_dbus_connection_remove_timeout_locked (DBusConnection *connection,
DBusTimeout *timeout)
{
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_connection_remove_timeout (connection, timeout);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
DBusHashIter iter;
DBusList *link;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_hash_iter_init (connection->handler_table, &iter);
while (_dbus_hash_iter_next (&iter))
link = next;
}
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
connection = data;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_connection_acquire_io_path (connection, -1);
retval = _dbus_transport_handle_watch (connection->transport,
watch, condition);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_connection_update_dispatch_status_locked (connection, status);
dbus_connection_ref (DBusConnection *connection)
{
_dbus_return_if_fail (connection != NULL);
+
+ /* The connection lock is better than the global
+ * lock in the atomic increment fallback
+ */
- dbus_mutex_lock (connection->mutex);
+#ifdef DBUS_HAVE_ATOMIC_INT
+ _dbus_atomic_inc (&connection->refcount);
+#else
+ CONNECTION_LOCK (connection);
_dbus_assert (connection->refcount > 0);
connection->refcount += 1;
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
+#endif
}
static void
dbus_bool_t last_unref;
_dbus_return_if_fail (connection != NULL);
+
+ /* The connection lock is better than the global
+ * lock in the atomic increment fallback
+ */
- dbus_mutex_lock (connection->mutex);
+#ifdef DBUS_HAVE_ATOMIC_INT
+ last_unref = (_dbus_atomic_dec (&connection->refcount) == 0);
+#else
+ CONNECTION_LOCK (connection);
_dbus_assert (connection->refcount > 0);
printf ("unref() connection %p count = %d\n", connection, connection->refcount);
#endif
- dbus_mutex_unlock (connection->mutex);
-
+ CONNECTION_UNLOCK (connection);
+#endif
+
if (last_unref)
_dbus_connection_last_unref (connection);
}
{
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_transport_disconnect (connection->transport);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
+}
+
+static dbus_bool_t
+_dbus_connection_get_is_connected_unlocked (DBusConnection *connection)
+{
+ return _dbus_transport_get_is_connected (connection->transport);
}
/**
_dbus_return_val_if_fail (connection != NULL, FALSE);
- dbus_mutex_lock (connection->mutex);
- res = _dbus_transport_get_is_connected (connection->transport);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_LOCK (connection);
+ res = _dbus_connection_get_is_connected_unlocked (connection);
+ CONNECTION_UNLOCK (connection);
return res;
}
_dbus_return_val_if_fail (connection != NULL, FALSE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
res = _dbus_transport_get_is_authenticated (connection->transport);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return res;
}
if (preallocated == NULL)
return NULL;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
preallocated->queue_link = _dbus_list_alloc_link (NULL);
if (preallocated->queue_link == NULL)
preallocated->connection = connection;
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return preallocated;
failed_0:
dbus_free (preallocated);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return NULL;
}
_dbus_return_if_fail (preallocated->connection == connection);
_dbus_return_if_fail (dbus_message_get_name (message) != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
preallocated->queue_link->data = message;
_dbus_list_prepend_link (&connection->outgoing_messages,
_dbus_connection_wakeup_mainloop (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
connection = reply_handler_data->connection;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
if (reply_handler_data->timeout_link)
{
_dbus_connection_queue_synthesized_message_link (connection,
status = _dbus_connection_get_dispatch_status_unlocked (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_connection_update_dispatch_status_locked (connection, status);
return FALSE;
}
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
/* Add timeout */
if (!_dbus_connection_add_timeout (connection, timeout))
{
reply_handler_data_free (data);
_dbus_timeout_unref (timeout);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return FALSE;
}
if (!_dbus_message_handler_add_connection (reply_handler, connection))
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
reply_handler_data_free (data);
return FALSE;
}
"No reply within specified time");
if (!reply)
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
reply_handler_data_free (data);
return FALSE;
}
reply_link = _dbus_list_alloc_link (reply);
if (!reply)
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
dbus_message_unref (reply);
reply_handler_data_free (data);
return FALSE;
/* Insert the serial in the pending replies hash. */
if (!_dbus_hash_table_insert_int (connection->pending_replies, serial, data))
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
reply_handler_data_free (data);
return FALSE;
}
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
if (!dbus_connection_send (connection, message, NULL))
{
/* Flush message queue */
dbus_connection_flush (connection);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_get_current_time (&start_tv_sec, &start_tv_usec);
end_tv_sec = start_tv_sec + timeout_milliseconds / 1000;
{
status = _dbus_connection_get_dispatch_status_unlocked (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n",
dbus_message_get_name (reply));
else
dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_connection_update_dispatch_status_locked (connection, status);
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
while (connection->n_outgoing > 0 &&
- dbus_connection_get_is_connected (connection))
+ _dbus_connection_get_is_connected_unlocked (connection))
_dbus_connection_do_iteration (connection,
DBUS_ITERATION_DO_READING |
DBUS_ITERATION_DO_WRITING |
status = _dbus_connection_get_dispatch_status_unlocked (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_connection_update_dispatch_status_locked (connection, status);
}
if (status != DBUS_DISPATCH_DATA_REMAINS)
return NULL;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
if (connection->message_borrowed != NULL)
_dbus_connection_wait_for_borrowed (connection);
if (message)
connection->message_borrowed = message;
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return message;
}
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (message != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_assert (message == connection->message_borrowed);
connection->message_borrowed = NULL;
dbus_condvar_wake_all (connection->message_returned_cond);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (message != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_assert (message == connection->message_borrowed);
connection->message_borrowed = NULL;
dbus_condvar_wake_all (connection->message_returned_cond);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/* See dbus_connection_pop_message, but requires the caller to own
if (status != DBUS_DISPATCH_DATA_REMAINS)
return NULL;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
message = _dbus_connection_pop_message_unlocked (connection);
_dbus_verbose ("Returning popped message %p\n", message);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return message;
}
DBusDispatchStatusFunction function;
void *data;
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_connection_ref_unlocked (connection);
changed = new_status != connection->last_dispatch_status;
function = connection->dispatch_status_function;
data = connection->dispatch_status_data;
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
if (changed && function)
{
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
status = _dbus_connection_get_dispatch_status_unlocked (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return status;
}
return status;
}
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
/* We need to ref the connection since the callback could potentially
* drop the last ref to it
/* another thread dispatched our stuff */
_dbus_connection_release_dispatch (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
status = dbus_connection_get_dispatch_status (connection);
if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
{
_dbus_connection_release_dispatch (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_connection_failed_pop (connection, message_link);
_dbus_connection_update_dispatch_status_locked (connection, DBUS_DISPATCH_NEED_MEMORY);
/* We're still protected from dispatch() reentrancy here
* since we acquired the dispatcher
*/
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
link = _dbus_list_get_first_link (&filter_list_copy);
while (link != NULL)
NULL);
_dbus_list_clear (&filter_list_copy);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
/* Did a reply we were waiting on get filtered? */
if (reply_handler_data && result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
if (reply_handler_data)
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_verbose (" running reply handler on message %p\n", message);
result = _dbus_message_handler_handle_message (reply_handler_data->handler,
connection, message);
reply_handler_data_free (reply_handler_data);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
goto out;
}
/* We're still protected from dispatch() reentrancy here
* since we acquired the dispatcher
*/
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_verbose (" running app handler on message %p (%s)\n",
message, dbus_message_get_name (message));
result = _dbus_message_handler_handle_message (handler, connection,
message);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)
goto out;
}
out:
_dbus_connection_release_dispatch (connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
_dbus_list_free_link (message_link);
dbus_message_unref (message); /* don't want the message to count in max message limits
* in computing dispatch status
_dbus_return_val_if_fail (connection != NULL, FALSE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
/* ref connection for slightly better reentrancy */
_dbus_connection_ref_unlocked (connection);
toggled_function,
data, free_data_function);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
/* drop our paranoid refcount */
dbus_connection_unref (connection);
_dbus_return_val_if_fail (connection != NULL, FALSE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
/* ref connection for slightly better reentrancy */
_dbus_connection_ref_unlocked (connection);
toggled_function,
data, free_data_function);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
/* drop our paranoid refcount */
dbus_connection_unref (connection);
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
old_data = connection->wakeup_main_data;
old_free_data = connection->free_wakeup_main_data;
connection->wakeup_main_data = data;
connection->free_wakeup_main_data = free_data_function;
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
/* Callback outside the lock */
if (old_free_data)
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
old_data = connection->dispatch_status_data;
old_free_data = connection->free_dispatch_status_data;
connection->dispatch_status_data = data;
connection->free_dispatch_status_data = free_data_function;
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
/* Callback outside the lock */
if (old_free_data)
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (uid != NULL, FALSE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
if (!_dbus_transport_get_is_authenticated (connection->transport))
result = FALSE;
else
result = _dbus_transport_get_unix_user (connection->transport,
uid);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return result;
}
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_transport_set_unix_user_function (connection->transport,
function, data, free_data_function,
&old_data, &old_free_function);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
if (old_free_function != NULL)
(* old_free_function) (old_data);
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (handler != NULL, FALSE);
-
- dbus_mutex_lock (connection->mutex);
+
+ CONNECTION_LOCK (connection);
if (!_dbus_message_handler_add_connection (handler, connection))
{
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return FALSE;
}
handler))
{
_dbus_message_handler_remove_connection (handler, connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return FALSE;
}
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return TRUE;
}
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (handler != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
if (!_dbus_list_remove_last (&connection->filter_list, handler))
{
_dbus_warn ("Tried to remove a DBusConnection filter that had not been added\n");
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return;
}
_dbus_message_handler_remove_connection (handler, connection);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
_dbus_return_val_if_fail (n_messages >= 0, FALSE);
_dbus_return_val_if_fail (n_messages == 0 || messages_to_handle != NULL, FALSE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
i = 0;
while (i < n_messages)
{
++i;
}
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return TRUE;
failed:
messages_to_handle,
i);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return FALSE;
}
_dbus_return_if_fail (n_messages >= 0);
_dbus_return_if_fail (n_messages == 0 || messages_to_handle != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
i = 0;
while (i < n_messages)
{
++i;
}
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
static DBusDataSlotAllocator slot_allocator;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (slot >= 0, FALSE);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
retval = _dbus_data_slot_list_set (&slot_allocator,
&connection->slot_list,
slot, data, free_data_func,
&old_free_func, &old_data);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
if (retval)
{
_dbus_return_val_if_fail (connection != NULL, NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
res = _dbus_data_slot_list_get (&slot_allocator,
&connection->slot_list,
slot);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return res;
}
{
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_transport_set_max_message_size (connection->transport,
size);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
_dbus_return_val_if_fail (connection != NULL, 0);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
res = _dbus_transport_get_max_message_size (connection->transport);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return res;
}
{
_dbus_return_if_fail (connection != NULL);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
_dbus_transport_set_max_received_size (connection->transport,
size);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
}
/**
_dbus_return_val_if_fail (connection != NULL, 0);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
res = _dbus_transport_get_max_received_size (connection->transport);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return res;
}
_dbus_return_val_if_fail (connection != NULL, 0);
- dbus_mutex_lock (connection->mutex);
+ CONNECTION_LOCK (connection);
res = _dbus_counter_get_value (connection->outgoing_counter);
- dbus_mutex_unlock (connection->mutex);
+ CONNECTION_UNLOCK (connection);
return res;
}
--- /dev/null
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* test-profile.c Program that does basic message-response for timing
+ *
+ * Copyright (C) 2003 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 1.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <config.h>
+#include <glib.h>
+#include "dbus-glib.h"
+#include <stdlib.h>
+
+#define N_CLIENT_THREADS 1
+#define N_ITERATIONS 2000
+#define ECHO_MESSAGE "org.freedesktop.DBus.Test.EchoProfile"
+static const char *address;
+
+static void
+send_echo_message (DBusConnection *connection)
+{
+ DBusMessage *message;
+
+ message = dbus_message_new (ECHO_MESSAGE, NULL);
+ dbus_message_append_args (message,
+ DBUS_TYPE_STRING, "Hello World!",
+ DBUS_TYPE_INT32, 123456,
+ DBUS_TYPE_INVALID);
+ dbus_connection_send (connection, message, NULL);
+ dbus_message_unref (message);
+ dbus_connection_flush (connection);
+}
+
+static DBusHandlerResult
+client_filter (DBusMessageHandler *handler,
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ int *iterations = user_data;
+
+ if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT))
+ {
+ g_printerr ("Client thread disconnected\n");
+ exit (1);
+ }
+ else if (dbus_message_has_name (message,
+ ECHO_MESSAGE))
+ {
+ *iterations += 1;
+ send_echo_message (connection);
+ if (*iterations > N_ITERATIONS)
+ {
+ g_print ("Completed %d iterations\n", N_ITERATIONS);
+ exit (0);
+ }
+ }
+
+ return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+}
+
+static void*
+thread_func (void *data)
+{
+ DBusError error;
+ GMainContext *context;
+ GMainLoop *loop;
+ DBusMessageHandler *handler;
+ DBusConnection *connection;
+ int iterations;
+
+ g_printerr ("Starting client thread\n");
+
+ dbus_error_init (&error);
+ connection = dbus_connection_open (address, &error);
+ if (connection == NULL)
+ {
+ g_printerr ("could not open connection: %s\n", error.message);
+ dbus_error_free (&error);
+ exit (1);
+ }
+
+ iterations = 0;
+
+ handler = dbus_message_handler_new (client_filter,
+ &iterations, NULL);
+
+ if (!dbus_connection_add_filter (connection,
+ handler))
+ g_error ("no memory");
+
+ /* FIXME we leak the handler */
+
+ context = g_main_context_new ();
+ loop = g_main_loop_new (context, FALSE);
+
+ dbus_connection_setup_with_g_main (connection, context);
+
+ g_printerr ("Client thread sending message to prime pingpong\n");
+ send_echo_message (connection);
+ g_printerr ("Client thread sent message\n");
+
+ g_printerr ("Client thread entering main loop\n");
+ g_main_loop_run (loop);
+ g_printerr ("Client thread exiting main loop\n");
+
+ g_main_loop_unref (loop);
+ g_main_context_unref (context);
+
+ return NULL;
+}
+
+static DBusHandlerResult
+server_filter (DBusMessageHandler *handler,
+ DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT))
+ {
+ g_printerr ("Server thread disconnected\n");
+ exit (1);
+ }
+ else if (dbus_message_has_name (message,
+ ECHO_MESSAGE))
+ {
+ send_echo_message (connection);
+ }
+
+ return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+}
+
+static void
+new_connection_callback (DBusServer *server,
+ DBusConnection *new_connection,
+ void *user_data)
+{
+ DBusMessageHandler *handler;
+
+ dbus_connection_ref (new_connection);
+ dbus_connection_setup_with_g_main (new_connection, NULL);
+
+ handler = dbus_message_handler_new (server_filter,
+ NULL, NULL);
+
+ if (!dbus_connection_add_filter (new_connection,
+ handler))
+ g_error ("no memory");
+
+
+ /* FIXME we leak the handler */
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *loop;
+ DBusError error;
+ DBusServer *server;
+ int i;
+
+ g_thread_init (NULL);
+ dbus_gthread_init ();
+
+ dbus_error_init (&error);
+ server = dbus_server_listen ("unix:tmpdir="DBUS_TEST_SOCKET_DIR,
+ &error);
+ if (server == NULL)
+ {
+ g_printerr ("Could not start server: %s\n",
+ error.message);
+ return 1;
+ }
+
+ address = dbus_server_get_address (server);
+
+ dbus_server_set_new_connection_function (server,
+ new_connection_callback,
+ NULL, NULL);
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ dbus_server_setup_with_g_main (server, NULL);
+
+ for (i = 0; i < N_CLIENT_THREADS; i++)
+ {
+ g_thread_create (thread_func, NULL, FALSE, NULL);
+ }
+
+ g_printerr ("Server thread entering main loop\n");
+ g_main_loop_run (loop);
+ g_printerr ("Server thread exiting main loop\n");
+
+ dbus_server_unref (server);
+
+ g_main_loop_unref (loop);
+
+ return 0;
+}
+