From: Tomas Bzatek Date: Wed, 6 Jun 2012 17:44:39 +0000 (+0200) Subject: gdbus: Implement g_dbus_connection_get_last_serial() X-Git-Tag: 2.33.3~60 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=032e8dabd15133952c7c4f9da05605380b17f79f;p=platform%2Fupstream%2Fglib.git gdbus: Implement g_dbus_connection_get_last_serial() This patch brings an ability to retrieve serial number of the last message sent within the current thread. https://bugzilla.gnome.org/show_bug.cgi?id=676825 --- diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt index 5f4a7df..5e25b5d 100644 --- a/docs/reference/gio/gio-sections.txt +++ b/docs/reference/gio/gio-sections.txt @@ -2629,6 +2629,7 @@ g_dbus_connection_get_unique_name GDBusCapabilityFlags g_dbus_connection_get_capabilities g_dbus_connection_get_peer_credentials +g_dbus_connection_get_last_serial GDBusCallFlags g_dbus_connection_call g_dbus_connection_call_finish diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c index d886f8f..7f421c4 100644 --- a/gio/gdbusconnection.c +++ b/gio/gdbusconnection.c @@ -444,6 +444,9 @@ struct _GDBusConnection GHashTable *map_object_path_to_es; /* gchar* -> ExportedSubtree* */ GHashTable *map_id_to_es; /* guint -> ExportedSubtree* */ + /* Map used for storing last used serials for each thread, protected by @lock */ + GHashTable *map_thread_to_last_serial; + /* Structure used for message filters, protected by @lock */ GPtrArray *filters; @@ -672,6 +675,8 @@ g_dbus_connection_finalize (GObject *object) g_hash_table_unref (connection->map_id_to_es); g_hash_table_unref (connection->map_object_path_to_es); + g_hash_table_unref (connection->map_thread_to_last_serial); + g_main_context_unref (connection->main_context_at_construction); g_free (connection->machine_id); @@ -1090,6 +1095,9 @@ g_dbus_connection_init (GDBusConnection *connection) connection->map_id_to_es = g_hash_table_new (g_direct_hash, g_direct_equal); + connection->map_thread_to_last_serial = g_hash_table_new (g_direct_hash, + g_direct_equal); + connection->main_context_at_construction = g_main_context_ref_thread_default (); connection->filters = g_ptr_array_new (); @@ -1571,6 +1579,38 @@ g_dbus_connection_close_sync (GDBusConnection *connection, /* ---------------------------------------------------------------------------------------------------- */ +/** + * g_dbus_connection_get_last_serial: + * @connection: A #GDBusConnection. + * + * Retrieves the last serial number assigned to a #GDBusMessage on + * the current thread. This includes messages sent via both low-level + * API such as g_dbus_connection_send_message() as well as + * high-level API such as g_dbus_connection_emit_signal(), + * g_dbus_connection_call() or g_dbus_proxy_call(). + * + * Returns: the last used serial or zero when no message has been sent + * within the current thread. + * + * Since: 2.34 + */ +guint32 +g_dbus_connection_get_last_serial (GDBusConnection *connection) +{ + guint32 ret; + + g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0); + + CONNECTION_LOCK (connection); + ret = GPOINTER_TO_UINT (g_hash_table_lookup (connection->map_thread_to_last_serial, + g_thread_self ())); + CONNECTION_UNLOCK (connection); + + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + /* Can be called by any thread, with the connection lock held */ static gboolean g_dbus_connection_send_message_unlocked (GDBusConnection *connection, @@ -1645,6 +1685,15 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection, if (out_serial != NULL) *out_serial = serial_to_use; + /* store used serial for the current thread */ + /* TODO: watch the thread disposal and remove associated record + * from hashtable + * - see https://bugzilla.gnome.org/show_bug.cgi?id=676825#c7 + */ + g_hash_table_replace (connection->map_thread_to_last_serial, + g_thread_self (), + GUINT_TO_POINTER (serial_to_use)); + if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL)) g_dbus_message_set_serial (message, serial_to_use); diff --git a/gio/gdbusconnection.h b/gio/gdbusconnection.h index 9b164d5..6c1ec5c 100644 --- a/gio/gdbusconnection.h +++ b/gio/gdbusconnection.h @@ -89,6 +89,10 @@ GIOStream *g_dbus_connection_get_stream (GDBusConnection const gchar *g_dbus_connection_get_guid (GDBusConnection *connection); const gchar *g_dbus_connection_get_unique_name (GDBusConnection *connection); GCredentials *g_dbus_connection_get_peer_credentials (GDBusConnection *connection); + +GLIB_AVAILABLE_IN_2_34 +guint32 g_dbus_connection_get_last_serial (GDBusConnection *connection); + gboolean g_dbus_connection_get_exit_on_close (GDBusConnection *connection); void g_dbus_connection_set_exit_on_close (GDBusConnection *connection, gboolean exit_on_close); diff --git a/gio/gio.symbols b/gio/gio.symbols index 5c8bbd1..c30c8d1 100644 --- a/gio/gio.symbols +++ b/gio/gio.symbols @@ -1233,6 +1233,7 @@ g_dbus_connection_get_capabilities g_dbus_connection_get_exit_on_close g_dbus_connection_get_guid g_dbus_connection_get_peer_credentials +g_dbus_connection_get_last_serial g_dbus_connection_get_stream g_dbus_connection_get_unique_name g_dbus_connection_is_closed diff --git a/gio/tests/gdbus-connection.c b/gio/tests/gdbus-connection.c index 39c915c..353b09e 100644 --- a/gio/tests/gdbus-connection.c +++ b/gio/tests/gdbus-connection.c @@ -995,6 +995,95 @@ test_connection_filter (void) session_bus_down (); } +/* ---------------------------------------------------------------------------------------------------- */ + +#define NUM_THREADS 50 + +static void +send_bogus_message (GDBusConnection *c, guint32 *out_serial) +{ + GDBusMessage *m; + GError *error; + + m = g_dbus_message_new_method_call ("org.freedesktop.DBus", /* name */ + "/org/freedesktop/DBus", /* path */ + "org.freedesktop.DBus", /* interface */ + "GetNameOwner"); + g_dbus_message_set_body (m, g_variant_new ("(s)", "org.freedesktop.DBus")); + error = NULL; + g_dbus_connection_send_message (c, m, G_DBUS_SEND_MESSAGE_FLAGS_NONE, out_serial, &error); + g_assert_no_error (error); +} + +static gpointer +serials_thread_func (GDBusConnection *c) +{ + guint32 message_serial; + + /* No calls on this thread yet */ + g_assert_cmpint (g_dbus_connection_get_last_serial(c), ==, 0); + + /* Send a bogus message and store its serial */ + message_serial = 0; + send_bogus_message (c, &message_serial); + + /* Give it some time to actually send the message out */ + g_usleep (250000); + + g_assert_cmpint (g_dbus_connection_get_last_serial(c), !=, 0); + g_assert_cmpint (g_dbus_connection_get_last_serial(c), ==, message_serial); + + return NULL; +} + +static void +test_connection_serials (void) +{ + GDBusConnection *c; + GError *error; + GThread *pool[NUM_THREADS]; + int i; + + session_bus_up (); + + error = NULL; + c = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + g_assert_no_error (error); + g_assert (c != NULL); + + /* Status after initialization */ + g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 1); + + /* Send a bogus message */ + send_bogus_message (c, NULL); + g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 2); + + /* Start the threads */ + for (i = 0; i < NUM_THREADS; i++) + pool[i] = g_thread_new (NULL, (GThreadFunc) serials_thread_func, c); + + /* Wait until threads are finished */ + for (i = 0; i < NUM_THREADS; i++) + { + g_thread_join (pool[i]); + g_thread_unref (pool[i]); + } + + /* No calls in between on this thread, should be the last value */ + g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 2); + + send_bogus_message (c, NULL); + + /* All above calls + calls in threads */ + g_assert_cmpint (g_dbus_connection_get_last_serial (c), ==, 3 + NUM_THREADS); + + g_object_unref (c); + + session_bus_down (); +} + +/* ---------------------------------------------------------------------------------------------------- */ + static void test_connection_basic (void) { @@ -1066,5 +1155,6 @@ main (int argc, g_test_add_func ("/gdbus/connection/send", test_connection_send); g_test_add_func ("/gdbus/connection/signals", test_connection_signals); g_test_add_func ("/gdbus/connection/filter", test_connection_filter); + g_test_add_func ("/gdbus/connection/serials", test_connection_serials); return g_test_run(); }