Bug 618882 – No way to ensure that a message is sent

Add g_dbus_connection_flush{_finish,sync}().

https://bugzilla.gnome.org/show_bug.cgi?id=618882

Signed-off-by: David Zeuthen <davidz@redhat.com>
This commit is contained in:
David Zeuthen
2010-07-07 15:00:23 -04:00
parent d4f35ae9ed
commit 62a1ccf526
9 changed files with 406 additions and 3 deletions

View File

@@ -882,6 +882,151 @@ g_dbus_connection_get_capabilities (GDBusConnection *connection)
return connection->priv->capabilities;
}
/* ---------------------------------------------------------------------------------------------------- */
static void
flush_in_thread_func (GSimpleAsyncResult *res,
GObject *object,
GCancellable *cancellable)
{
GError *error;
error = NULL;
if (!g_dbus_connection_flush_sync (G_DBUS_CONNECTION (object),
cancellable,
&error))
{
g_simple_async_result_set_from_error (res, error);
g_error_free (error);
}
}
/**
* g_dbus_connection_flush:
* @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.
*
* Asynchronously flushes @connection, that is, writes all queued
* outgoing message to the transport and then flushes the transport
* (using g_output_stream_flush_async()). This is useful in programs
* that wants to emit a D-Bus signal and then exit
* immediately. Without flushing the connection, there is no guarantee
* that the message has been sent to the networking buffers in the OS
* kernel.
*
* 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_flush_finish() to get the result of the
* operation. See g_dbus_connection_flush_sync() for the synchronous
* version.
*
* Since: 2.26
*/
void
g_dbus_connection_flush (GDBusConnection *connection,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *simple;
g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
simple = g_simple_async_result_new (NULL,
callback,
user_data,
g_dbus_connection_flush);
g_simple_async_result_run_in_thread (simple,
flush_in_thread_func,
G_PRIORITY_DEFAULT,
cancellable);
g_object_unref (simple);
}
/**
* g_dbus_connection_flush_finish:
* @connection: A #GDBusConnection.
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to g_dbus_connection_flush().
* @error: Return location for error or %NULL.
*
* Finishes an operation started with g_dbus_connection_flush().
*
* Returns: %TRUE if the operation succeeded, %FALSE if @error is set.
*
* Since: 2.26
*/
gboolean
g_dbus_connection_flush_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_flush);
if (g_simple_async_result_propagate_error (simple, error))
goto out;
ret = TRUE;
out:
return ret;
}
/**
* g_dbus_connection_flush_sync:
* @connection: A #GDBusConnection.
* @cancellable: A #GCancellable or %NULL.
* @error: Return location for error or %NULL.
*
* Synchronously flushes @connection. The calling thread is blocked
* until this is done. See g_dbus_connection_flush() 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_flush_sync (GDBusConnection *connection,
GCancellable *cancellable,
GError **error)
{
gboolean ret;
g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
ret = FALSE;
if (connection->priv->closed)
{
g_set_error_literal (error,
G_IO_ERROR,
G_IO_ERROR_CLOSED,
_("The connection is closed"));
goto out;
}
ret = _g_dbus_worker_flush_sync (connection->priv->worker,
cancellable,
error);
out:
return ret;
}
/* ---------------------------------------------------------------------------------------------------- */
@@ -955,7 +1100,14 @@ set_closed_unlocked (GDBusConnection *connection,
*
* Closes @connection. Note that this never causes the process to
* exit (this might only happen if the other end of a shared message
* bus connection disconnects).
* bus connection disconnects, see #GDBusConnection:exit-on-close).
*
* Once the stream is closed, all operations will return
* %G_IO_ERROR_CLOSED.
*
* Note that 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 does nothing.
*
@@ -1091,8 +1243,7 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
* submitting the message to the underlying transport.
*
* If @connection is closed then the operation will fail with
* %G_IO_ERROR_CLOSED. If @cancellable is canceled, the operation will
* fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
* %G_IO_ERROR_CLOSED. If @message is not well-formed,
* the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
*
* See <xref linkend="gdbus-server"/> and <xref