summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-pending-call.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-pending-call.c')
-rw-r--r--dbus/dbus-pending-call.c146
1 files changed, 97 insertions, 49 deletions
diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c
index 7a65ad62..84ca7ae0 100644
--- a/dbus/dbus-pending-call.c
+++ b/dbus/dbus-pending-call.c
@@ -22,11 +22,11 @@
*/
#include "dbus-internals.h"
-#include "dbus-message-pending.h"
+#include "dbus-connection-internal.h"
+#include "dbus-pending-call.h"
#include "dbus-list.h"
#include "dbus-threads.h"
#include "dbus-test.h"
-#include "dbus-connection-internal.h"
/**
* @defgroup DBusPendingCallInternals DBusPendingCall implementation details
@@ -39,55 +39,64 @@
*/
/**
- * @brief Internals of DBusPendingCall
- *
- * Object representing a reply message that we're waiting for.
- */
-struct DBusPendingCall
-{
- DBusAtomic refcount; /**< reference count */
-
- DBusPendingCallNotifyFunction function; /**< Notifier when reply arrives. */
- void *user_data; /**< user data for function */
- DBusFreeFunction free_user_data; /**< free the user data */
-
- DBusConnection *connection; /**< Connections we're associated with */
- DBusMessage *reply; /**< Reply (after we've received it) */
- DBusTimeout *timeout; /**< Timeout */
-
- DBusList *timeout_link; /**< Preallocated timeout response */
-
- dbus_uint32_t reply_serial; /**< Expected serial of reply */
-
- unsigned int completed : 1; /**< TRUE if completed */
- unsigned int timeout_added : 1; /**< Have added the timeout */
-};
-
-/**
* Creates a new pending reply object.
*
* @param connection connection where reply will arrive
- * @param reply_serial reply serial of the expected reply
+ * @param timeout_milliseconds length of timeout, -1 for default
+ * @param timeout_handler timeout handler, takes pending call as data
* @returns a new #DBusPendingCall or #NULL if no memory.
*/
DBusPendingCall*
-_dbus_pending_call_new (DBusConnection *connection,
- dbus_uint32_t reply_serial)
+_dbus_pending_call_new (DBusConnection *connection,
+ int timeout_milliseconds,
+ DBusTimeoutHandler timeout_handler)
{
DBusPendingCall *pending;
+ DBusTimeout *timeout;
+ _dbus_return_val_if_fail (timeout_milliseconds >= 0 || timeout_milliseconds == -1, FALSE);
+
+ if (timeout_milliseconds == -1)
+ timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
+
pending = dbus_new (DBusPendingCall, 1);
if (pending == NULL)
return NULL;
+ timeout = _dbus_timeout_new (timeout_milliseconds,
+ timeout_handler,
+ pending, NULL);
+
+ if (timeout == NULL)
+ {
+ dbus_free (pending);
+ return NULL;
+ }
+
pending->refcount.value = 1;
pending->connection = connection;
- pending->reply_serial = reply_serial;
-
+ pending->timeout = timeout;
+
return pending;
}
+/**
+ * Calls notifier function for the pending call
+ * and sets the call to completed.
+ *
+ * @param pending the pending call
+ *
+ */
+void
+_dbus_pending_call_notify (DBusPendingCall *pending)
+{
+ pending->completed = TRUE;
+
+ if (pending->function)
+ (* pending->function) (pending, pending->user_data);
+}
+
/** @} */
/**
@@ -138,14 +147,24 @@ dbus_pending_call_unref (DBusPendingCall *pending)
if (last_unref)
{
+ /* If we get here, we should be already detached
+ * from the connection, or never attached.
+ */
+ _dbus_assert (pending->connection == NULL);
+ _dbus_assert (!pending->timeout_added);
+
+ /* this assumes we aren't holding connection lock... */
if (pending->free_user_data)
(* pending->free_user_data) (pending->user_data);
-
- if (pending->connection != NULL)
+ if (pending->timeout != NULL)
+ _dbus_timeout_unref (pending->timeout);
+
+ if (pending->timeout_link)
{
- _dbus_connection_pending_destroyed_locked (connection, pending);
- pending->connection = NULL;
+ dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
+ _dbus_list_free_link (pending->timeout_link);
+ pending->timeout_link = NULL;
}
if (pending->reply)
@@ -179,37 +198,66 @@ dbus_pending_call_set_notify (DBusPendingCall *pending,
_dbus_return_if_fail (pending != NULL);
- _DBUS_LOCK (pending_call);
old_free_func = pending->free_user_data;
old_user_data = pending->user_data;
pending->user_data = user_data;
pending->free_user_data = free_user_data;
pending->function = function;
- _DBUS_UNLOCK (pending_call);
if (old_free_func)
(* old_free_func) (old_user_data);
}
-/** @} */
+/**
+ * Cancels the pending call, such that any reply
+ * or error received will just be ignored.
+ * Drops at least one reference to the #DBusPendingCall
+ * so will free the call if nobody else is holding
+ * a reference.
+ *
+ * @param pending the pending call
+ */
+void
+dbus_pending_call_cancel (DBusPendingCall *pending)
+{
+ if (pending->connection)
+ _dbus_connection_remove_pending_call (pending->connection,
+ pending);
+}
-#ifdef DBUS_BUILD_TESTS
-static DBusPendingResult
-test_pending (DBusPendingCall *pending,
- DBusConnection *connection,
- DBusMessage *message,
- void *user_data)
+/**
+ * Checks whether the pending call has received a reply
+ * yet, or not.
+ *
+ * @param pending the pending call
+ * @returns #TRUE if a reply has been received
+ */
+dbus_bool_t
+dbus_pending_call_get_completed (DBusPendingCall *pending)
{
- return DBUS_PENDING_RESULT_NOT_YET_HANDLED;
+ return pending->completed;
}
-static void
-free_test_data (void *data)
+/**
+ * Gets the reply, or returns #NULL if none has been received yet. The
+ * reference count is not incremented on the returned message, so you
+ * have to keep a reference count on the pending call (or add one
+ * to the message).
+ *
+ * @param pending the pending call
+ * @returns the reply message or #NULL.
+ */
+DBusMessage*
+dbus_pending_call_get_reply (DBusPendingCall *pending)
{
- /* does nothing */
+ return pending->reply;
}
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+
/**
* @ingroup DBusPendingCallInternals
* Unit test for DBusPendingCall.