GDBusConnection: Fix up g_dbus_connection_close()

... so it is async, cancelable and returns an error. Also provide a
synchronous version.

This is an API/ABI break but it is expected that only very few
applications use this API.

Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
David Zeuthen 2010-07-14 12:37:32 -04:00
parent 14e37ef796
commit 914b046226
5 changed files with 158 additions and 19 deletions

View File

@ -2360,6 +2360,8 @@ g_dbus_connection_new_for_address_finish
g_dbus_connection_new_for_address_sync g_dbus_connection_new_for_address_sync
g_dbus_connection_start_message_processing g_dbus_connection_start_message_processing
g_dbus_connection_close g_dbus_connection_close
g_dbus_connection_close_finish
g_dbus_connection_close_sync
g_dbus_connection_is_closed g_dbus_connection_is_closed
g_dbus_connection_flush g_dbus_connection_flush
g_dbus_connection_flush_finish g_dbus_connection_flush_finish

View File

@ -1036,6 +1036,7 @@ g_dbus_connection_flush_sync (GDBusConnection *connection,
gboolean ret; gboolean ret;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE); g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
ret = FALSE; ret = FALSE;
@ -1122,46 +1123,162 @@ set_closed_unlocked (GDBusConnection *connection,
/* ---------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------- */
static void
close_in_thread_func (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GError *error;
error = NULL;
if (!g_dbus_connection_close_sync (G_DBUS_CONNECTION (object),
cancellable,
&error))
{
g_simple_async_result_set_from_error (res, error);
g_error_free (error);
}
}
/** /**
* g_dbus_connection_close: * g_dbus_connection_close:
* @connection: A #GDBusConnection. * @connection: A #GDBusConnection.
* @cancellable: A #GCancellable or %NULL.
* @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL if you don't
* care about the result.
* @user_data: The data to pass to @callback.
* *
* Closes @connection. Note that this never causes the process to * Closes @connection. Note that this never causes the process to
* exit (this might only happen if the other end of a shared message * exit (this might only happen if the other end of a shared message
* bus connection disconnects, see #GDBusConnection:exit-on-close). * bus connection disconnects, see #GDBusConnection:exit-on-close).
* *
* Once the stream is closed, all operations will return * Once the connection is closed, operations such as sending a message
* will return with the error %G_IO_ERROR_CLOSED. Closing a connection
* will not automatically flush the connection so queued messages may
* be lost. Use g_dbus_connection_flush() if you need such guarantees.
*
* If @connection is already closed, this method fails with
* %G_IO_ERROR_CLOSED. * %G_IO_ERROR_CLOSED.
* *
* Note that closing a connection will not automatically flush the * When @connection has been closed, the #GDBusConnection::closed
* connection so queued messages may be lost. Use * signal is emitted in the <link
* g_dbus_connection_flush() if you need such guarantees. * linkend="g-main-context-push-thread-default">thread-default main
* loop</link> of the thread that @connection was constructed in.
* *
* If @connection is already closed, this method does nothing. * This is an asynchronous method. When the operation is finished,
* @callback will be invoked in the <link
* linkend="g-main-context-push-thread-default">thread-default main
* loop</link> of the thread you are calling this method from. You can
* then call g_dbus_connection_close_finish() to get the result of the
* operation. See g_dbus_connection_close_sync() for the synchronous
* version.
* *
* Since: 2.26 * Since: 2.26
*/ */
void void
g_dbus_connection_close (GDBusConnection *connection) g_dbus_connection_close (GDBusConnection *connection,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{ {
GSimpleAsyncResult *simple;
g_return_if_fail (G_IS_DBUS_CONNECTION (connection)); g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
simple = g_simple_async_result_new (NULL,
callback,
user_data,
g_dbus_connection_close);
g_simple_async_result_run_in_thread (simple,
close_in_thread_func,
G_PRIORITY_DEFAULT,
cancellable);
g_object_unref (simple);
}
/**
* g_dbus_connection_close_finish:
* @connection: A #GDBusConnection.
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_close().
* @error: Return location for error or %NULL.
*
* Finishes an operation started with g_dbus_connection_close().
*
* Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
*
* Since: 2.26
*/
gboolean
g_dbus_connection_close_finish (GDBusConnection *connection,
GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
gboolean ret;
ret = FALSE;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
g_return_val_if_fail (G_IS_ASYNC_RESULT (res), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_close);
if (g_simple_async_result_propagate_error (simple, error))
goto out;
ret = TRUE;
out:
return ret;
}
/**
* g_dbus_connection_close_sync:
* @connection: A #GDBusConnection.
* @cancellable: A #GCancellable or %NULL.
* @error: Return location for error or %NULL.
*
* Synchronously closees @connection. The calling thread is blocked
* until this is done. See g_dbus_connection_close() for the
* asynchronous version of this method and more details about what it
* does.
*
* Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
*
* Since: 2.26
*/
gboolean
g_dbus_connection_close_sync (GDBusConnection *connection,
GCancellable *cancellable,
GError **error)
{
gboolean ret;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
ret = FALSE;
CONNECTION_LOCK (connection); CONNECTION_LOCK (connection);
if (!connection->closed) if (!connection->closed)
{ {
GError *error = NULL; ret = g_io_stream_close (connection->stream,
cancellable,
/* TODO: do this async */ error);
//g_debug ("closing connection %p's stream %p", connection, connection->stream); if (ret)
if (!g_io_stream_close (connection->stream, NULL, &error)) set_closed_unlocked (connection, FALSE, NULL);
{ }
g_warning ("Error closing stream: %s", error->message); else
g_error_free (error); {
} g_set_error_literal (error,
G_IO_ERROR,
set_closed_unlocked (connection, FALSE, NULL); G_IO_ERROR_CLOSED,
_("The connection is closed"));
} }
CONNECTION_UNLOCK (connection); CONNECTION_UNLOCK (connection);
return ret;
} }
/* ---------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------- */

View File

@ -85,7 +85,6 @@ GDBusConnection *g_dbus_connection_new_for_address_sync (const gchar
void g_dbus_connection_start_message_processing (GDBusConnection *connection); void g_dbus_connection_start_message_processing (GDBusConnection *connection);
gboolean g_dbus_connection_is_closed (GDBusConnection *connection); gboolean g_dbus_connection_is_closed (GDBusConnection *connection);
void g_dbus_connection_close (GDBusConnection *connection);
GIOStream *g_dbus_connection_get_stream (GDBusConnection *connection); GIOStream *g_dbus_connection_get_stream (GDBusConnection *connection);
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);
@ -97,6 +96,19 @@ GDBusCapabilityFlags g_dbus_connection_get_capabilities (GDBusConnection
/* ---------------------------------------------------------------------------------------------------- */ /* ---------------------------------------------------------------------------------------------------- */
void g_dbus_connection_close (GDBusConnection *connection,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean g_dbus_connection_close_finish (GDBusConnection *connection,
GAsyncResult *res,
GError **error);
gboolean g_dbus_connection_close_sync (GDBusConnection *connection,
GCancellable *cancellable,
GError **error);
/* ---------------------------------------------------------------------------------------------------- */
void g_dbus_connection_flush (GDBusConnection *connection, void g_dbus_connection_flush (GDBusConnection *connection,
GCancellable *cancellable, GCancellable *cancellable,
GAsyncReadyCallback callback, GAsyncReadyCallback callback,

View File

@ -1539,6 +1539,8 @@ g_dbus_connection_get_unique_name
g_dbus_connection_is_closed g_dbus_connection_is_closed
g_dbus_connection_set_exit_on_close g_dbus_connection_set_exit_on_close
g_dbus_connection_close g_dbus_connection_close
g_dbus_connection_close_finish
g_dbus_connection_close_sync
g_dbus_connection_flush g_dbus_connection_flush
g_dbus_connection_flush_finish g_dbus_connection_flush_finish
g_dbus_connection_flush_sync g_dbus_connection_flush_sync

View File

@ -39,6 +39,7 @@ static GMainLoop *loop = NULL;
static void static void
test_connection_life_cycle (void) test_connection_life_cycle (void)
{ {
gboolean ret;
GDBusConnection *c; GDBusConnection *c;
GDBusConnection *c2; GDBusConnection *c2;
GError *error; GError *error;
@ -88,9 +89,14 @@ test_connection_life_cycle (void)
g_assert_no_error (error); g_assert_no_error (error);
g_assert (c2 != NULL); g_assert (c2 != NULL);
g_assert (!g_dbus_connection_is_closed (c2)); g_assert (!g_dbus_connection_is_closed (c2));
g_dbus_connection_close (c2); ret = g_dbus_connection_close_sync (c2, NULL, &error);
g_assert_no_error (error);
g_assert (ret);
_g_assert_signal_received (c2, "closed"); _g_assert_signal_received (c2, "closed");
g_assert (g_dbus_connection_is_closed (c2)); g_assert (g_dbus_connection_is_closed (c2));
ret = g_dbus_connection_close_sync (c2, NULL, &error);
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED);
g_assert (!ret);
g_object_unref (c2); g_object_unref (c2);
/* /*