From a6c8a71b1bcba04b63812a61f668e87af0922e5e Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Thu, 14 Aug 2003 22:49:13 +0000 Subject: 2003-08-14 Havoc Pennington * dbus/dbus-pending-call.c: start on new object that will replace DBusMessageHandler and ReplyHandlerData for tracking outstanding replies * dbus/dbus-gproxy.c: start on proxy object used to communicate with remote interfaces * dbus/dbus-gidl.c: do the boring boilerplate in here --- dbus/dbus-pending-call.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 dbus/dbus-pending-call.c (limited to 'dbus/dbus-pending-call.c') diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c new file mode 100644 index 00000000..7a65ad62 --- /dev/null +++ b/dbus/dbus-pending-call.c @@ -0,0 +1,225 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-pending-call.c Object representing a call in progress. + * + * Copyright (C) 2002, 2003 Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "dbus-internals.h" +#include "dbus-message-pending.h" +#include "dbus-list.h" +#include "dbus-threads.h" +#include "dbus-test.h" +#include "dbus-connection-internal.h" + +/** + * @defgroup DBusPendingCallInternals DBusPendingCall implementation details + * @ingroup DBusInternals + * @brief DBusPendingCall private implementation details. + * + * The guts of DBusPendingCall and its methods. + * + * @{ + */ + +/** + * @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 + * @returns a new #DBusPendingCall or #NULL if no memory. + */ +DBusPendingCall* +_dbus_pending_call_new (DBusConnection *connection, + dbus_uint32_t reply_serial) +{ + DBusPendingCall *pending; + + pending = dbus_new (DBusPendingCall, 1); + + if (pending == NULL) + return NULL; + + pending->refcount.value = 1; + pending->connection = connection; + pending->reply_serial = reply_serial; + + return pending; +} + +/** @} */ + +/** + * @defgroup DBusPendingCall DBusPendingCall + * @ingroup DBus + * @brief Pending reply to a method call message + * + * A DBusPendingCall is an object representing an + * expected reply. A #DBusPendingCall can be created + * when you send a message that should have a reply. + * + * @{ + */ + +/** + * @typedef DBusPendingCall + * + * Opaque data type representing a message pending. + */ + +/** + * Increments the reference count on a pending call. + * + * @param pending the pending call object + */ +void +dbus_pending_call_ref (DBusPendingCall *pending) +{ + _dbus_return_if_fail (pending != NULL); + + _dbus_atomic_inc (&pending->refcount); +} + +/** + * Decrements the reference count on a pending call, + * freeing it if the count reaches 0. + * + * @param pending the pending call object + */ +void +dbus_pending_call_unref (DBusPendingCall *pending) +{ + dbus_bool_t last_unref; + + _dbus_return_if_fail (pending != NULL); + + last_unref = (_dbus_atomic_dec (&pending->refcount) == 1); + + if (last_unref) + { + if (pending->free_user_data) + (* pending->free_user_data) (pending->user_data); + + + if (pending->connection != NULL) + { + _dbus_connection_pending_destroyed_locked (connection, pending); + pending->connection = NULL; + } + + if (pending->reply) + { + dbus_message_unref (pending->reply); + pending->reply = NULL; + } + + dbus_free (pending); + } +} + +/** + * Sets a notification function to be called when the reply is + * received or the pending call times out. + * + * @param pending the pending call + * @param function notifier function + * @param user_data data to pass to notifier function + * @param free_user_data function to free the user data + * + */ +void +dbus_pending_call_set_notify (DBusPendingCall *pending, + DBusPendingCallNotifyFunction function, + void *user_data, + DBusFreeFunction free_user_data) +{ + DBusFreeFunction old_free_func; + void *old_user_data; + + _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); +} + +/** @} */ + +#ifdef DBUS_BUILD_TESTS +static DBusPendingResult +test_pending (DBusPendingCall *pending, + DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + return DBUS_PENDING_RESULT_NOT_YET_HANDLED; +} + +static void +free_test_data (void *data) +{ + /* does nothing */ +} + +/** + * @ingroup DBusPendingCallInternals + * Unit test for DBusPendingCall. + * + * @returns #TRUE on success. + */ +dbus_bool_t +_dbus_pending_call_test (const char *test_data_dir) +{ + + return TRUE; +} +#endif /* DBUS_BUILD_TESTS */ -- cgit From ef614207fc4f03e5cc02faeb109f739eb1ccdf31 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 15 Aug 2003 04:17:58 +0000 Subject: 2003-08-15 Havoc Pennington * dbus/dbus-connection.c, dbus/dbus-pending-call.c: Finish the pending call stuff --- dbus/dbus-pending-call.c | 146 +++++++++++++++++++++++++++++++---------------- 1 file changed, 97 insertions(+), 49 deletions(-) (limited to 'dbus/dbus-pending-call.c') 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 @@ -38,56 +38,65 @@ * @{ */ -/** - * @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. -- cgit From a1b0bd33408f03894987ac32b4e6b46c6a15a594 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Fri, 15 Aug 2003 23:10:12 +0000 Subject: 2003-08-15 Havoc Pennington * dbus/dbus-pending-call.c (dbus_pending_call_block): implement * dbus/dbus-connection.c (dbus_connection_send_with_reply_and_block): factor out internals; change to convert any error replies to DBusError instead of returning them as a message --- dbus/dbus-pending-call.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'dbus/dbus-pending-call.c') diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index 84ca7ae0..2b6021e9 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -254,6 +254,31 @@ dbus_pending_call_get_reply (DBusPendingCall *pending) return pending->reply; } +/** + * Block until the pending call is completed. The blocking is as with + * dbus_connection_send_with_reply_and_block(); it does not enter the + * main loop or process other messages, it simply waits for the reply + * in question. + * + * @todo when you start blocking, the timeout is reset, but it should + * really only use time remaining since the pending call was created. + * + * @param pending the pending call + */ +void +dbus_pending_call_block (DBusPendingCall *pending) +{ + DBusMessage *message; + + message = _dbus_connection_block_for_reply (pending->connection, + pending->reply_serial, + dbus_timeout_get_interval (pending->timeout)); + + _dbus_connection_lock (pending->connection); + _dbus_pending_call_complete_and_unlock (pending, message); + dbus_message_unref (message); +} + /** @} */ #ifdef DBUS_BUILD_TESTS -- cgit From 583994cb3b7f5562fb7b8c37b4cb0d5af78e4ce2 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Wed, 17 Sep 2003 03:52:07 +0000 Subject: 2003-09-15 Havoc Pennington * dbus/dbus-pending-call.c: add the get/set object data boilerplate as for DBusConnection, etc. Use generic object data for the notify callback. * glib/dbus-gparser.c (parse_node): parse child nodes * tools/dbus-viewer.c: more hacking on the dbus-viewer * glib/dbus-gutils.c (_dbus_gutils_split_path): add a file to contain functions shared between the convenience lib and the installed lib * glib/Makefile.am (libdbus_glib_1_la_LDFLAGS): add -export-symbols-regex to the GLib library * dbus/dbus-object-tree.c (_dbus_object_tree_dispatch_and_unlock): fix the locking in here, and add a default handler for Introspect() that just returns sub-nodes. 2003-09-14 Havoc Pennington * glib/dbus-gthread.c (dbus_g_thread_init): rename to make g_foo rather than gfoo consistent * glib/dbus-gproxy.h: delete for now, move contents to dbus-glib.h, because the include files don't work right since we aren't in the dbus/ subdir. * glib/dbus-gproxy.c (dbus_gproxy_send): finish implementing (dbus_gproxy_end_call): finish (dbus_gproxy_begin_call): finish * glib/dbus-gmain.c (dbus_set_g_error): new * glib/dbus-gobject.c (handle_introspect): include information about child nodes in the introspection * dbus/dbus-connection.c (dbus_connection_list_registered): new function to help in implementation of introspection * dbus/dbus-object-tree.c (_dbus_object_tree_list_registered_and_unlock): new function 2003-09-12 Havoc Pennington * glib/dbus-gidl.h: add common base class for all the foo_info types * tools/dbus-viewer.c: add GTK-based introspection UI thingy similar to kdcop * test/Makefile.am: try test srcdir -ef . in addition to test srcdir = ., one of them should work (yeah lame) * glib/Makefile.am: build the "idl" parser stuff as a convenience library * glib/dbus-gparser.h: make description_load routines return NodeInfo* not Parser* * Makefile.am (SUBDIRS): build test dir after all library dirs * configure.in: add GTK+ detection --- dbus/dbus-pending-call.c | 171 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 151 insertions(+), 20 deletions(-) (limited to 'dbus/dbus-pending-call.c') diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index 2b6021e9..dad444e3 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -38,6 +38,8 @@ * @{ */ +static dbus_int32_t notify_user_data_slot = -1; + /** * Creates a new pending reply object. * @@ -58,11 +60,17 @@ _dbus_pending_call_new (DBusConnection *connection, if (timeout_milliseconds == -1) timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; + + if (!dbus_pending_call_allocate_data_slot (¬ify_user_data_slot)) + return NULL; pending = dbus_new (DBusPendingCall, 1); if (pending == NULL) - return NULL; + { + dbus_pending_call_free_data_slot (¬ify_user_data_slot); + return NULL; + } timeout = _dbus_timeout_new (timeout_milliseconds, timeout_handler, @@ -70,6 +78,7 @@ _dbus_pending_call_new (DBusConnection *connection, if (timeout == NULL) { + dbus_pending_call_free_data_slot (¬ify_user_data_slot); dbus_free (pending); return NULL; } @@ -77,6 +86,8 @@ _dbus_pending_call_new (DBusConnection *connection, pending->refcount.value = 1; pending->connection = connection; pending->timeout = timeout; + + _dbus_data_slot_list_init (&pending->slot_list); return pending; } @@ -94,7 +105,13 @@ _dbus_pending_call_notify (DBusPendingCall *pending) pending->completed = TRUE; if (pending->function) - (* pending->function) (pending, pending->user_data); + { + void *user_data; + user_data = dbus_pending_call_get_data (pending, + notify_user_data_slot); + + (* pending->function) (pending, user_data); + } } /** @} */ @@ -154,9 +171,8 @@ dbus_pending_call_unref (DBusPendingCall *pending) _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); - + _dbus_data_slot_list_free (&pending->slot_list); + if (pending->timeout != NULL) _dbus_timeout_unref (pending->timeout); @@ -174,6 +190,8 @@ dbus_pending_call_unref (DBusPendingCall *pending) } dbus_free (pending); + + dbus_pending_call_free_data_slot (¬ify_user_data_slot); } } @@ -185,28 +203,24 @@ dbus_pending_call_unref (DBusPendingCall *pending) * @param function notifier function * @param user_data data to pass to notifier function * @param free_user_data function to free the user data - * + * @returns #FALSE if not enough memory */ -void +dbus_bool_t dbus_pending_call_set_notify (DBusPendingCall *pending, DBusPendingCallNotifyFunction function, void *user_data, DBusFreeFunction free_user_data) { - DBusFreeFunction old_free_func; - void *old_user_data; - - _dbus_return_if_fail (pending != NULL); + _dbus_return_val_if_fail (pending != NULL, FALSE); - 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; + /* could invoke application code! */ + if (!dbus_pending_call_set_data (pending, notify_user_data_slot, + user_data, free_user_data)) + return FALSE; + pending->function = function; - if (old_free_func) - (* old_free_func) (old_user_data); + return TRUE; } /** @@ -230,9 +244,10 @@ dbus_pending_call_cancel (DBusPendingCall *pending) * Checks whether the pending call has received a reply * yet, or not. * + * @todo not thread safe? I guess it has to lock though it sucks + * * @param pending the pending call - * @returns #TRUE if a reply has been received - */ + * @returns #TRUE if a reply has been received */ dbus_bool_t dbus_pending_call_get_completed (DBusPendingCall *pending) { @@ -245,6 +260,9 @@ dbus_pending_call_get_completed (DBusPendingCall *pending) * have to keep a reference count on the pending call (or add one * to the message). * + * @todo not thread safe? I guess it has to lock though it sucks + * @todo maybe to make this threadsafe, it should be steal_reply(), i.e. only one thread can ever get the message + * * @param pending the pending call * @returns the reply message or #NULL. */ @@ -260,6 +278,9 @@ dbus_pending_call_get_reply (DBusPendingCall *pending) * main loop or process other messages, it simply waits for the reply * in question. * + * If the pending call is already completed, this function returns + * immediately. + * * @todo when you start blocking, the timeout is reset, but it should * really only use time remaining since the pending call was created. * @@ -269,6 +290,9 @@ void dbus_pending_call_block (DBusPendingCall *pending) { DBusMessage *message; + + if (dbus_pending_call_get_completed (pending)) + return; message = _dbus_connection_block_for_reply (pending->connection, pending->reply_serial, @@ -279,6 +303,113 @@ dbus_pending_call_block (DBusPendingCall *pending) dbus_message_unref (message); } +static DBusDataSlotAllocator slot_allocator; +_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots); + +/** + * Allocates an integer ID to be used for storing application-specific + * data on any DBusPendingCall. The allocated ID may then be used + * with dbus_pending_call_set_data() and dbus_pending_call_get_data(). + * The passed-in slot must be initialized to -1, and is filled in + * with the slot ID. If the passed-in slot is not -1, it's assumed + * to be already allocated, and its refcount is incremented. + * + * The allocated slot is global, i.e. all DBusPendingCall objects will + * have a slot with the given integer ID reserved. + * + * @param slot_p address of a global variable storing the slot + * @returns #FALSE on failure (no memory) + */ +dbus_bool_t +dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p) +{ + return _dbus_data_slot_allocator_alloc (&slot_allocator, + _DBUS_LOCK_NAME (pending_call_slots), + slot_p); +} + +/** + * Deallocates a global ID for #DBusPendingCall data slots. + * dbus_pending_call_get_data() and dbus_pending_call_set_data() may + * no longer be used with this slot. Existing data stored on existing + * DBusPendingCall objects will be freed when the #DBusPendingCall is + * finalized, but may not be retrieved (and may only be replaced if + * someone else reallocates the slot). When the refcount on the + * passed-in slot reaches 0, it is set to -1. + * + * @param slot_p address storing the slot to deallocate + */ +void +dbus_pending_call_free_data_slot (dbus_int32_t *slot_p) +{ + _dbus_return_if_fail (*slot_p >= 0); + + _dbus_data_slot_allocator_free (&slot_allocator, slot_p); +} + +/** + * Stores a pointer on a #DBusPendingCall, along + * with an optional function to be used for freeing + * the data when the data is set again, or when + * the pending call is finalized. The slot number + * must have been allocated with dbus_pending_call_allocate_data_slot(). + * + * @param pending the pending_call + * @param slot the slot number + * @param data the data to store + * @param free_data_func finalizer function for the data + * @returns #TRUE if there was enough memory to store the data + */ +dbus_bool_t +dbus_pending_call_set_data (DBusPendingCall *pending, + dbus_int32_t slot, + void *data, + DBusFreeFunction free_data_func) +{ + DBusFreeFunction old_free_func; + void *old_data; + dbus_bool_t retval; + + _dbus_return_val_if_fail (pending != NULL, FALSE); + _dbus_return_val_if_fail (slot >= 0, FALSE); + + retval = _dbus_data_slot_list_set (&slot_allocator, + &pending->slot_list, + slot, data, free_data_func, + &old_free_func, &old_data); + + if (retval) + { + if (old_free_func) + (* old_free_func) (old_data); + } + + return retval; +} + +/** + * Retrieves data previously set with dbus_pending_call_set_data(). + * The slot must still be allocated (must not have been freed). + * + * @param pending the pending_call + * @param slot the slot to get data from + * @returns the data, or #NULL if not found + */ +void* +dbus_pending_call_get_data (DBusPendingCall *pending, + dbus_int32_t slot) +{ + void *res; + + _dbus_return_val_if_fail (pending != NULL, NULL); + + res = _dbus_data_slot_list_get (&slot_allocator, + &pending->slot_list, + slot); + + return res; +} + /** @} */ #ifdef DBUS_BUILD_TESTS -- cgit