X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-pending-call.c;h=e1de656a69d983f4a8e80345f6c4a65b7af58b89;hb=f1b9aac417d8fb716d6ed19128fe429e8a41adba;hp=e6ece9dd27413bc69cb63d6bac4e9220a2a65a1c;hpb=222bd07e9df5e3b5a367d1282b43fd3a827a7552;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index e6ece9d..e1de656 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -1,4 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-pending-call.c Object representing a call in progress. * * Copyright (C) 2002, 2003 Red Hat Inc. @@ -17,10 +17,11 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include #include "dbus-internals.h" #include "dbus-connection-internal.h" #include "dbus-pending-call-internal.h" @@ -44,9 +45,19 @@ * * Opaque object representing a reply message that we're waiting for. */ + +/** + * shorter and more visible way to write _dbus_connection_lock() + */ #define CONNECTION_LOCK(connection) _dbus_connection_lock(connection) +/** + * shorter and more visible way to write _dbus_connection_unlock() + */ #define CONNECTION_UNLOCK(connection) _dbus_connection_unlock(connection) +/** + * Implementation details of #DBusPendingCall - all fields are private. + */ struct DBusPendingCall { DBusAtomic refcount; /**< reference count */ @@ -73,7 +84,7 @@ static dbus_int32_t notify_user_data_slot = -1; * Creates a new pending reply object. * * @param connection connection where reply will arrive - * @param timeout_milliseconds length of timeout, -1 for default + * @param timeout_milliseconds length of timeout, -1 for default, INT_MAX for no timeout * @param timeout_handler timeout handler, takes pending call as data * @returns a new #DBusPendingCall or #NULL if no memory. */ @@ -90,14 +101,6 @@ _dbus_pending_call_new_unlocked (DBusConnection *connection, if (timeout_milliseconds == -1) timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE; - /* it would probably seem logical to pass in _DBUS_INT_MAX for - * infinite timeout, but then math in - * _dbus_connection_block_for_reply would get all overflow-prone, so - * smack that down. - */ - if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6) - timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6; - if (!dbus_pending_call_allocate_data_slot (¬ify_user_data_slot)) return NULL; @@ -109,24 +112,30 @@ _dbus_pending_call_new_unlocked (DBusConnection *connection, return NULL; } - timeout = _dbus_timeout_new (timeout_milliseconds, - timeout_handler, - pending, NULL); - - if (timeout == NULL) + if (timeout_milliseconds != _DBUS_INT_MAX) { - dbus_pending_call_free_data_slot (¬ify_user_data_slot); - dbus_free (pending); - return NULL; + timeout = _dbus_timeout_new (timeout_milliseconds, + timeout_handler, + pending, NULL); + + if (timeout == NULL) + { + dbus_pending_call_free_data_slot (¬ify_user_data_slot); + dbus_free (pending); + return NULL; + } + + pending->timeout = timeout; } - + else + { + pending->timeout = NULL; + } + pending->refcount.value = 1; pending->connection = connection; _dbus_connection_ref_unlocked (pending->connection); - pending->timeout = timeout; - - _dbus_data_slot_list_init (&pending->slot_list); return pending; @@ -189,6 +198,13 @@ _dbus_pending_call_complete (DBusPendingCall *pending) } } +/** + * If the pending call hasn't been timed out, add its timeout + * error reply to the connection's incoming message queue. + * + * @param pending the pending call + * @param connection the connection the call was sent to + */ void _dbus_pending_call_queue_timeout_error_unlocked (DBusPendingCall *pending, DBusConnection *connection) @@ -238,7 +254,7 @@ _dbus_pending_call_set_timeout_added_unlocked (DBusPendingCall *pending, * Retrives the timeout * * @param pending the pending_call - * @returns a timeout object + * @returns a timeout object or NULL if call has no timeout */ DBusTimeout * _dbus_pending_call_get_timeout_unlocked (DBusPendingCall *pending) @@ -346,26 +362,6 @@ _dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending, return TRUE; } -/** @} */ - -/** - * @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, * while the lock on its connection is already held. @@ -381,32 +377,6 @@ _dbus_pending_call_ref_unlocked (DBusPendingCall *pending) return pending; } -/** - * Increments the reference count on a pending call. - * - * @param pending the pending call object - * @returns the pending call object - */ -DBusPendingCall * -dbus_pending_call_ref (DBusPendingCall *pending) -{ - _dbus_return_val_if_fail (pending != NULL, NULL); - - /* The connection lock is better than the global - * lock in the atomic increment fallback - */ -#ifdef DBUS_HAVE_ATOMIC_INT - _dbus_atomic_inc (&pending->refcount); -#else - CONNECTION_LOCK (pending->connection); - _dbus_assert (pending->refcount.value > 0); - - pending->refcount.value += 1; - CONNECTION_UNLOCK (pending->connection); -#endif - - return pending; -} static void _dbus_pending_call_last_unref (DBusPendingCall *pending) @@ -474,6 +444,111 @@ _dbus_pending_call_unref_and_unlock (DBusPendingCall *pending) } /** + * Checks whether the pending call has received a reply + * yet, or not. Assumes connection lock is held. + * + * @param pending the pending call + * @returns #TRUE if a reply has been received + */ +dbus_bool_t +_dbus_pending_call_get_completed_unlocked (DBusPendingCall *pending) +{ + return pending->completed; +} + +static DBusDataSlotAllocator slot_allocator; +_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots); + +/** + * 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_unlocked (DBusPendingCall *pending, + dbus_int32_t slot, + void *data, + DBusFreeFunction free_data_func) +{ + DBusFreeFunction old_free_func; + void *old_data; + dbus_bool_t retval; + + retval = _dbus_data_slot_list_set (&slot_allocator, + &pending->slot_list, + slot, data, free_data_func, + &old_free_func, &old_data); + + /* Drop locks to call out to app code */ + CONNECTION_UNLOCK (pending->connection); + + if (retval) + { + if (old_free_func) + (* old_free_func) (old_data); + } + + CONNECTION_LOCK (pending->connection); + + return retval; +} + +/** @} */ + +/** + * @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 + * @returns the pending call object + */ +DBusPendingCall * +dbus_pending_call_ref (DBusPendingCall *pending) +{ + _dbus_return_val_if_fail (pending != NULL, NULL); + + /* The connection lock is better than the global + * lock in the atomic increment fallback + */ +#ifdef DBUS_HAVE_ATOMIC_INT + _dbus_atomic_inc (&pending->refcount); +#else + CONNECTION_LOCK (pending->connection); + _dbus_assert (pending->refcount.value > 0); + + pending->refcount.value += 1; + CONNECTION_UNLOCK (pending->connection); +#endif + + return pending; +} + +/** * Decrements the reference count on a pending call, * freeing it if the count reaches 0. * @@ -539,33 +614,28 @@ dbus_pending_call_set_notify (DBusPendingCall *pending, * Cancels the pending call, such that any reply or error received * will just be ignored. Drops the dbus library's internal reference * to the #DBusPendingCall so will free the call if nobody else is - * holding a reference. However you usually get a reference - * from dbus_connection_send() so probably your app owns a ref also. + * holding a reference. However you usually get a reference from + * dbus_connection_send_with_reply() so probably your app owns a ref + * also. + * + * Note that canceling a pending call will not simulate a + * timed-out call; if a call times out, then a timeout error reply is + * received. If you cancel the call, no reply is received unless the + * the reply was already received before you canceled. * * @param pending the pending call */ void dbus_pending_call_cancel (DBusPendingCall *pending) { + _dbus_return_if_fail (pending != NULL); + _dbus_connection_remove_pending_call (pending->connection, pending); } /** * Checks whether the pending call has received a reply - * yet, or not. Assumes connection lock is held. - * - * @param pending the pending call - * @returns #TRUE if a reply has been received - */ -dbus_bool_t -_dbus_pending_call_get_completed_unlocked (DBusPendingCall *pending) -{ - return pending->completed; -} - -/** - * Checks whether the pending call has received a reply * yet, or not. * * @param pending the pending call @@ -576,6 +646,8 @@ dbus_pending_call_get_completed (DBusPendingCall *pending) { dbus_bool_t completed; + _dbus_return_val_if_fail (pending != NULL, FALSE); + CONNECTION_LOCK (pending->connection); completed = pending->completed; CONNECTION_UNLOCK (pending->connection); @@ -597,6 +669,7 @@ dbus_pending_call_steal_reply (DBusPendingCall *pending) { DBusMessage *message; + _dbus_return_val_if_fail (pending != NULL, NULL); _dbus_return_val_if_fail (pending->completed, NULL); _dbus_return_val_if_fail (pending->reply != NULL, NULL); @@ -621,18 +694,18 @@ dbus_pending_call_steal_reply (DBusPendingCall *pending) * * @todo when you start blocking, the timeout is reset, but it should * really only use time remaining since the pending call was created. + * This requires storing timestamps instead of intervals in the timeout * * @param pending the pending call */ void dbus_pending_call_block (DBusPendingCall *pending) { + _dbus_return_if_fail (pending != NULL); + _dbus_connection_block_pending_call (pending); } -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 @@ -650,8 +723,10 @@ _DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots); dbus_bool_t dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p) { + _dbus_return_val_if_fail (slot_p != NULL, FALSE); + return _dbus_data_slot_allocator_alloc (&slot_allocator, - _DBUS_LOCK_NAME (pending_call_slots), + &_DBUS_LOCK_NAME (pending_call_slots), slot_p); } @@ -669,6 +744,7 @@ dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p) void dbus_pending_call_free_data_slot (dbus_int32_t *slot_p) { + _dbus_return_if_fail (slot_p != NULL); _dbus_return_if_fail (*slot_p >= 0); _dbus_data_slot_allocator_free (&slot_allocator, slot_p); @@ -688,48 +764,6 @@ dbus_pending_call_free_data_slot (dbus_int32_t *slot_p) * @returns #TRUE if there was enough memory to store the data */ dbus_bool_t -_dbus_pending_call_set_data_unlocked (DBusPendingCall *pending, - dbus_int32_t slot, - void *data, - DBusFreeFunction free_data_func) -{ - DBusFreeFunction old_free_func; - void *old_data; - dbus_bool_t retval; - - retval = _dbus_data_slot_list_set (&slot_allocator, - &pending->slot_list, - slot, data, free_data_func, - &old_free_func, &old_data); - - /* Drop locks to call out to app code */ - CONNECTION_UNLOCK (pending->connection); - - if (retval) - { - if (old_free_func) - (* old_free_func) (old_data); - } - - CONNECTION_LOCK (pending->connection); - - return retval; -} - -/** - * 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,