mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
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
This commit is contained in:
parent
7ccfa9ce4b
commit
032e8dabd1
@ -2629,6 +2629,7 @@ g_dbus_connection_get_unique_name
|
|||||||
GDBusCapabilityFlags
|
GDBusCapabilityFlags
|
||||||
g_dbus_connection_get_capabilities
|
g_dbus_connection_get_capabilities
|
||||||
g_dbus_connection_get_peer_credentials
|
g_dbus_connection_get_peer_credentials
|
||||||
|
g_dbus_connection_get_last_serial
|
||||||
GDBusCallFlags
|
GDBusCallFlags
|
||||||
g_dbus_connection_call
|
g_dbus_connection_call
|
||||||
g_dbus_connection_call_finish
|
g_dbus_connection_call_finish
|
||||||
|
@ -444,6 +444,9 @@ struct _GDBusConnection
|
|||||||
GHashTable *map_object_path_to_es; /* gchar* -> ExportedSubtree* */
|
GHashTable *map_object_path_to_es; /* gchar* -> ExportedSubtree* */
|
||||||
GHashTable *map_id_to_es; /* guint -> 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 */
|
/* Structure used for message filters, protected by @lock */
|
||||||
GPtrArray *filters;
|
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_id_to_es);
|
||||||
g_hash_table_unref (connection->map_object_path_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_main_context_unref (connection->main_context_at_construction);
|
||||||
|
|
||||||
g_free (connection->machine_id);
|
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,
|
connection->map_id_to_es = g_hash_table_new (g_direct_hash,
|
||||||
g_direct_equal);
|
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->main_context_at_construction = g_main_context_ref_thread_default ();
|
||||||
|
|
||||||
connection->filters = g_ptr_array_new ();
|
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 */
|
/* Can be called by any thread, with the connection lock held */
|
||||||
static gboolean
|
static gboolean
|
||||||
g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
|
g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
|
||||||
@ -1645,6 +1685,15 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
|
|||||||
if (out_serial != NULL)
|
if (out_serial != NULL)
|
||||||
*out_serial = serial_to_use;
|
*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))
|
if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
|
||||||
g_dbus_message_set_serial (message, serial_to_use);
|
g_dbus_message_set_serial (message, serial_to_use);
|
||||||
|
|
||||||
|
@ -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_guid (GDBusConnection *connection);
|
||||||
const gchar *g_dbus_connection_get_unique_name (GDBusConnection *connection);
|
const gchar *g_dbus_connection_get_unique_name (GDBusConnection *connection);
|
||||||
GCredentials *g_dbus_connection_get_peer_credentials (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);
|
gboolean g_dbus_connection_get_exit_on_close (GDBusConnection *connection);
|
||||||
void g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
|
void g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
|
||||||
gboolean exit_on_close);
|
gboolean exit_on_close);
|
||||||
|
@ -1233,6 +1233,7 @@ g_dbus_connection_get_capabilities
|
|||||||
g_dbus_connection_get_exit_on_close
|
g_dbus_connection_get_exit_on_close
|
||||||
g_dbus_connection_get_guid
|
g_dbus_connection_get_guid
|
||||||
g_dbus_connection_get_peer_credentials
|
g_dbus_connection_get_peer_credentials
|
||||||
|
g_dbus_connection_get_last_serial
|
||||||
g_dbus_connection_get_stream
|
g_dbus_connection_get_stream
|
||||||
g_dbus_connection_get_unique_name
|
g_dbus_connection_get_unique_name
|
||||||
g_dbus_connection_is_closed
|
g_dbus_connection_is_closed
|
||||||
|
@ -995,6 +995,95 @@ test_connection_filter (void)
|
|||||||
session_bus_down ();
|
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
|
static void
|
||||||
test_connection_basic (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/send", test_connection_send);
|
||||||
g_test_add_func ("/gdbus/connection/signals", test_connection_signals);
|
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/filter", test_connection_filter);
|
||||||
|
g_test_add_func ("/gdbus/connection/serials", test_connection_serials);
|
||||||
return g_test_run();
|
return g_test_run();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user