Coverage report for dbus/dbus-pending-call.c.gcov

        -:    0:Source:dbus-pending-call.c
        -:    0:Graph:.libs/dbus-pending-call.gcno
        -:    0:Data:.libs/dbus-pending-call.gcda
        -:    0:Runs:11822
        -:    0:Programs:5
        -:    1:/* -*- mode: C; c-file-style: "gnu" -*- */
        -:    2:/* dbus-pending-call.c Object representing a call in progress.
        -:    3: *
        -:    4: * Copyright (C) 2002, 2003 Red Hat Inc.
        -:    5: *
        -:    6: * Licensed under the Academic Free License version 2.1
        -:    7: *
        -:    8: * This program is free software; you can redistribute it and/or modify
        -:    9: * it under the terms of the GNU General Public License as published by
        -:   10: * the Free Software Foundation; either version 2 of the License, or
        -:   11: * (at your option) any later version.
        -:   12: *
        -:   13: * This program is distributed in the hope that it will be useful,
        -:   14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
        -:   15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        -:   16: * GNU General Public License for more details.
        -:   17: *
        -:   18: * You should have received a copy of the GNU General Public License
        -:   19: * along with this program; if not, write to the Free Software
        -:   20: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        -:   21: *
        -:   22: */
        -:   23:
        -:   24:#include "dbus-internals.h"
        -:   25:#include "dbus-connection-internal.h"
        -:   26:#include "dbus-pending-call.h"
        -:   27:#include "dbus-list.h"
        -:   28:#include "dbus-threads.h"
        -:   29:#include "dbus-test.h"
        -:   30:
        -:   31:/**
        -:   32: * @defgroup DBusPendingCallInternals DBusPendingCall implementation details
        -:   33: * @ingroup DBusInternals
        -:   34: * @brief DBusPendingCall private implementation details.
        -:   35: *
        -:   36: * The guts of DBusPendingCall and its methods.
        -:   37: *
        -:   38: * @{
        -:   39: */
        -:   40:
        -:   41:static dbus_int32_t notify_user_data_slot = -1;
        -:   42:
        -:   43:/**
        -:   44: * Creates a new pending reply object.
        -:   45: *
        -:   46: * @param connection connection where reply will arrive
        -:   47: * @param timeout_milliseconds length of timeout, -1 for default
        -:   48: * @param timeout_handler timeout handler, takes pending call as data
        -:   49: * @returns a new #DBusPendingCall or #NULL if no memory.
        -:   50: */
        -:   51:DBusPendingCall*
        -:   52:_dbus_pending_call_new (DBusConnection    *connection,
        -:   53:                        int                timeout_milliseconds,
        -:   54:                        DBusTimeoutHandler timeout_handler)
function _dbus_pending_call_new called 1346 returned 100% blocks executed 67%
     1346:   55:{
        -:   56:  DBusPendingCall *pending;
        -:   57:  DBusTimeout *timeout;
        -:   58:
     1346:   59:  _dbus_assert (timeout_milliseconds >= 0 || timeout_milliseconds == -1);
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
branch  2 taken 100% (fallthrough)
branch  3 taken 0%
call    4 returned 100%
        -:   60:  
     1346:   61:  if (timeout_milliseconds == -1)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
     1346:   62:    timeout_milliseconds = _DBUS_DEFAULT_TIMEOUT_VALUE;
        -:   63:
        -:   64:  /* it would probably seem logical to pass in _DBUS_INT_MAX for
        -:   65:   * infinite timeout, but then math in
        -:   66:   * _dbus_connection_block_for_reply would get all overflow-prone, so
        -:   67:   * smack that down.
        -:   68:   */
     1346:   69:  if (timeout_milliseconds > _DBUS_ONE_HOUR_IN_MILLISECONDS * 6)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
    #####:   70:    timeout_milliseconds = _DBUS_ONE_HOUR_IN_MILLISECONDS * 6;
        -:   71:  
     1346:   72:  if (!dbus_pending_call_allocate_data_slot (&notify_user_data_slot))
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
    #####:   73:    return NULL;
        -:   74:  
     1346:   75:  pending = dbus_new0 (DBusPendingCall, 1);
call    0 returned 100%
        -:   76:  
     1346:   77:  if (pending == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:   78:    {
    #####:   79:      dbus_pending_call_free_data_slot (&notify_user_data_slot);
call    0 never executed
    #####:   80:      return NULL;
        -:   81:    }
        -:   82:
     1346:   83:  timeout = _dbus_timeout_new (timeout_milliseconds,
call    0 returned 100%
        -:   84:                               timeout_handler,
        -:   85:			       pending, NULL);  
        -:   86:
     1346:   87:  if (timeout == NULL)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:   88:    {
    #####:   89:      dbus_pending_call_free_data_slot (&notify_user_data_slot);
call    0 never executed
    #####:   90:      dbus_free (pending);
call    0 never executed
    #####:   91:      return NULL;
        -:   92:    }
        -:   93:  
     1346:   94:  pending->refcount.value = 1;
     1346:   95:  pending->connection = connection;
     1346:   96:  pending->timeout = timeout;
        -:   97:
     1346:   98:  _dbus_data_slot_list_init (&pending->slot_list);
call    0 returned 100%
        -:   99:  
     1346:  100:  return pending;
        -:  101:}
        -:  102:
        -:  103:/**
        -:  104: * Calls notifier function for the pending call
        -:  105: * and sets the call to completed.
        -:  106: *
        -:  107: * @param pending the pending call
        -:  108: * 
        -:  109: */
        -:  110:void
        -:  111:_dbus_pending_call_notify (DBusPendingCall *pending)
function _dbus_pending_call_notify called 1346 returned 100% blocks executed 60%
     1346:  112:{
     1346:  113:  _dbus_assert (!pending->completed);
call    0 returned 100%
        -:  114:  
     1346:  115:  pending->completed = TRUE;
        -:  116:
     1346:  117:  if (pending->function)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  118:    {
        -:  119:      void *user_data;
    #####:  120:      user_data = dbus_pending_call_get_data (pending,
call    0 never executed
        -:  121:                                              notify_user_data_slot);
        -:  122:      
    #####:  123:      (* pending->function) (pending, user_data);
call    0 never executed
        -:  124:    }
     1346:  125:}
        -:  126:
        -:  127:/** @} */
        -:  128:
        -:  129:/**
        -:  130: * @defgroup DBusPendingCall DBusPendingCall
        -:  131: * @ingroup  DBus
        -:  132: * @brief Pending reply to a method call message
        -:  133: *
        -:  134: * A DBusPendingCall is an object representing an
        -:  135: * expected reply. A #DBusPendingCall can be created
        -:  136: * when you send a message that should have a reply.
        -:  137: *
        -:  138: * @{
        -:  139: */
        -:  140:
        -:  141:/**
        -:  142: * @typedef DBusPendingCall
        -:  143: *
        -:  144: * Opaque data type representing a message pending.
        -:  145: */
        -:  146:
        -:  147:/**
        -:  148: * Increments the reference count on a pending call.
        -:  149: *
        -:  150: * @param pending the pending call object
        -:  151: * @returns the pending call object
        -:  152: */
        -:  153:DBusPendingCall *
        -:  154:dbus_pending_call_ref (DBusPendingCall *pending)
function dbus_pending_call_ref called 5384 returned 100% blocks executed 63%
     5384:  155:{
     5384:  156:  _dbus_return_val_if_fail (pending != NULL, NULL);
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
call    3 never executed
call    4 never executed
        -:  157:
     5384:  158:  _dbus_atomic_inc (&pending->refcount);
call    0 returned 100%
        -:  159:
     5384:  160:  return pending;
        -:  161:}
        -:  162:
        -:  163:/**
        -:  164: * Decrements the reference count on a pending call,
        -:  165: * freeing it if the count reaches 0.
        -:  166: *
        -:  167: * @param pending the pending call object
        -:  168: */
        -:  169:void
        -:  170:dbus_pending_call_unref (DBusPendingCall *pending)
function dbus_pending_call_unref called 6730 returned 100% blocks executed 81%
     6730:  171:{
        -:  172:  dbus_bool_t last_unref;
        -:  173:
     6730:  174:  _dbus_return_if_fail (pending != NULL);
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
call    3 never executed
call    4 never executed
        -:  175:
     6730:  176:  last_unref = (_dbus_atomic_dec (&pending->refcount) == 1);
call    0 returned 100%
        -:  177:
     6730:  178:  if (last_unref)
branch  0 taken 20% (fallthrough)
branch  1 taken 80%
        -:  179:    {
        -:  180:      /* If we get here, we should be already detached
        -:  181:       * from the connection, or never attached.
        -:  182:       */
     1346:  183:      _dbus_assert (pending->connection == NULL);
call    0 returned 100%
     1346:  184:      _dbus_assert (!pending->timeout_added);  
call    0 returned 100%
        -:  185:
        -:  186:      /* this assumes we aren't holding connection lock... */
     1346:  187:      _dbus_data_slot_list_free (&pending->slot_list);
call    0 returned 100%
        -:  188:      
     1346:  189:      if (pending->timeout != NULL)
branch  0 taken 100% (fallthrough)
branch  1 taken 0%
     1346:  190:        _dbus_timeout_unref (pending->timeout);
call    0 returned 100%
        -:  191:      
     1346:  192:      if (pending->timeout_link)
branch  0 taken 91% (fallthrough)
branch  1 taken 9%
        -:  193:        {
     1230:  194:          dbus_message_unref ((DBusMessage *)pending->timeout_link->data);
call    0 returned 100%
     1230:  195:          _dbus_list_free_link (pending->timeout_link);
call    0 returned 100%
     1230:  196:          pending->timeout_link = NULL;
        -:  197:        }
        -:  198:
     1346:  199:      if (pending->reply)
branch  0 taken 0% (fallthrough)
branch  1 taken 100%
        -:  200:        {
    #####:  201:          dbus_message_unref (pending->reply);
call    0 never executed
    #####:  202:          pending->reply = NULL;
        -:  203:        }
        -:  204:      
     1346:  205:      dbus_free (pending);
call    0 returned 100%
        -:  206:
     1346:  207:      dbus_pending_call_free_data_slot (&notify_user_data_slot);
call    0 returned 100%
        -:  208:    }
        -:  209:}
        -:  210:
        -:  211:/**
        -:  212: * Sets a notification function to be called when the reply is
        -:  213: * received or the pending call times out.
        -:  214: *
        -:  215: * @param pending the pending call
        -:  216: * @param function notifier function
        -:  217: * @param user_data data to pass to notifier function
        -:  218: * @param free_user_data function to free the user data
        -:  219: * @returns #FALSE if not enough memory
        -:  220: */
        -:  221:dbus_bool_t
        -:  222:dbus_pending_call_set_notify (DBusPendingCall              *pending,
        -:  223:                              DBusPendingCallNotifyFunction function,
        -:  224:                              void                         *user_data,
        -:  225:                              DBusFreeFunction              free_user_data)
function dbus_pending_call_set_notify called 0 returned 0% blocks executed 0%
    #####:  226:{
    #####:  227:  _dbus_return_val_if_fail (pending != NULL, FALSE);
call    0 never executed
branch  1 never executed
branch  2 never executed
call    3 never executed
call    4 never executed
        -:  228:
        -:  229:  /* could invoke application code! */
    #####:  230:  if (!dbus_pending_call_set_data (pending, notify_user_data_slot,
call    0 never executed
branch  1 never executed
branch  2 never executed
        -:  231:                                   user_data, free_user_data))
    #####:  232:    return FALSE;
        -:  233:  
    #####:  234:  pending->function = function;
        -:  235:
    #####:  236:  return TRUE;
        -:  237:}
        -:  238:
        -:  239:/**
        -:  240: * Cancels the pending call, such that any reply or error received
        -:  241: * will just be ignored.  Drops the dbus library's internal reference
        -:  242: * to the #DBusPendingCall so will free the call if nobody else is
        -:  243: * holding a reference. However you usually get a reference
        -:  244: * from dbus_connection_send() so probably your app owns a ref also.
        -:  245: * 
        -:  246: * @param pending the pending call
        -:  247: */
        -:  248:void
        -:  249:dbus_pending_call_cancel (DBusPendingCall *pending)
function dbus_pending_call_cancel called 0 returned 0% blocks executed 0%
    #####:  250:{
    #####:  251:  if (pending->connection)
branch  0 never executed
branch  1 never executed
    #####:  252:    _dbus_connection_remove_pending_call (pending->connection,
call    0 never executed
        -:  253:                                          pending);
    #####:  254:}
        -:  255:
        -:  256:/**
        -:  257: * Checks whether the pending call has received a reply
        -:  258: * yet, or not.
        -:  259: *
        -:  260: * @todo not thread safe? I guess it has to lock though it sucks
        -:  261: *
        -:  262: * @param pending the pending call
        -:  263: * @returns #TRUE if a reply has been received */
        -:  264:dbus_bool_t
        -:  265:dbus_pending_call_get_completed (DBusPendingCall *pending)
function dbus_pending_call_get_completed called 2693 returned 100% blocks executed 100%
     2693:  266:{
     2693:  267:  return pending->completed;
        -:  268:}
        -:  269:
        -:  270:/**
        -:  271: * Gets the reply, or returns #NULL if none has been received
        -:  272: * yet. Ownership of the reply message passes to the caller. This
        -:  273: * function can only be called once per pending call, since the reply
        -:  274: * message is tranferred to the caller.
        -:  275: * 
        -:  276: * @param pending the pending call
        -:  277: * @returns the reply message or #NULL.
        -:  278: */
        -:  279:DBusMessage*
        -:  280:dbus_pending_call_steal_reply (DBusPendingCall *pending)
function dbus_pending_call_steal_reply called 1346 returned 100% blocks executed 50%
     1346:  281:{
        -:  282:  DBusMessage *message;
        -:  283:  
     1346:  284:  _dbus_return_val_if_fail (pending->completed, NULL);
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
call    3 never executed
call    4 never executed
     1346:  285:  _dbus_return_val_if_fail (pending->reply != NULL, NULL);
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
call    3 never executed
call    4 never executed
        -:  286:  
     1346:  287:  message = pending->reply;
     1346:  288:  pending->reply = NULL;
        -:  289:
     1346:  290:  return message;
        -:  291:}
        -:  292:
        -:  293:/**
        -:  294: * Block until the pending call is completed.  The blocking is as with
        -:  295: * dbus_connection_send_with_reply_and_block(); it does not enter the
        -:  296: * main loop or process other messages, it simply waits for the reply
        -:  297: * in question.
        -:  298: *
        -:  299: * If the pending call is already completed, this function returns
        -:  300: * immediately.
        -:  301: *
        -:  302: * @todo when you start blocking, the timeout is reset, but it should
        -:  303: * really only use time remaining since the pending call was created.
        -:  304: *
        -:  305: * @param pending the pending call
        -:  306: */
        -:  307:void
        -:  308:dbus_pending_call_block (DBusPendingCall *pending)
function dbus_pending_call_block called 1346 returned 100% blocks executed 100%
     1346:  309:{
     1346:  310:  _dbus_connection_block_pending_call (pending);
call    0 returned 100%
     1346:  311:}
        -:  312:
        -:  313:static DBusDataSlotAllocator slot_allocator;
        -:  314:_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots);
        -:  315:
        -:  316:/**
        -:  317: * Allocates an integer ID to be used for storing application-specific
        -:  318: * data on any DBusPendingCall. The allocated ID may then be used
        -:  319: * with dbus_pending_call_set_data() and dbus_pending_call_get_data().
        -:  320: * The passed-in slot must be initialized to -1, and is filled in
        -:  321: * with the slot ID. If the passed-in slot is not -1, it's assumed
        -:  322: * to be already allocated, and its refcount is incremented.
        -:  323: * 
        -:  324: * The allocated slot is global, i.e. all DBusPendingCall objects will
        -:  325: * have a slot with the given integer ID reserved.
        -:  326: *
        -:  327: * @param slot_p address of a global variable storing the slot
        -:  328: * @returns #FALSE on failure (no memory)
        -:  329: */
        -:  330:dbus_bool_t
        -:  331:dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p)
function dbus_pending_call_allocate_data_slot called 1346 returned 100% blocks executed 100%
     1346:  332:{
     1346:  333:  return _dbus_data_slot_allocator_alloc (&slot_allocator,
call    0 returned 100%
        -:  334:                                          _DBUS_LOCK_NAME (pending_call_slots),
        -:  335:                                          slot_p);
        -:  336:}
        -:  337:
        -:  338:/**
        -:  339: * Deallocates a global ID for #DBusPendingCall data slots.
        -:  340: * dbus_pending_call_get_data() and dbus_pending_call_set_data() may
        -:  341: * no longer be used with this slot.  Existing data stored on existing
        -:  342: * DBusPendingCall objects will be freed when the #DBusPendingCall is
        -:  343: * finalized, but may not be retrieved (and may only be replaced if
        -:  344: * someone else reallocates the slot).  When the refcount on the
        -:  345: * passed-in slot reaches 0, it is set to -1.
        -:  346: *
        -:  347: * @param slot_p address storing the slot to deallocate
        -:  348: */
        -:  349:void
        -:  350:dbus_pending_call_free_data_slot (dbus_int32_t *slot_p)
function dbus_pending_call_free_data_slot called 1346 returned 100% blocks executed 67%
     1346:  351:{
     1346:  352:  _dbus_return_if_fail (*slot_p >= 0);
call    0 returned 100%
branch  1 taken 0% (fallthrough)
branch  2 taken 100%
call    3 never executed
call    4 never executed
        -:  353:  
     1346:  354:  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
call    0 returned 100%
        -:  355:}
        -:  356:
        -:  357:/**
        -:  358: * Stores a pointer on a #DBusPendingCall, along
        -:  359: * with an optional function to be used for freeing
        -:  360: * the data when the data is set again, or when
        -:  361: * the pending call is finalized. The slot number
        -:  362: * must have been allocated with dbus_pending_call_allocate_data_slot().
        -:  363: *
        -:  364: * @param pending the pending_call
        -:  365: * @param slot the slot number
        -:  366: * @param data the data to store
        -:  367: * @param free_data_func finalizer function for the data
        -:  368: * @returns #TRUE if there was enough memory to store the data
        -:  369: */
        -:  370:dbus_bool_t
        -:  371:dbus_pending_call_set_data (DBusPendingCall  *pending,
        -:  372:                            dbus_int32_t      slot,
        -:  373:                            void             *data,
        -:  374:                            DBusFreeFunction  free_data_func)
function dbus_pending_call_set_data called 0 returned 0% blocks executed 0%
    #####:  375:{
        -:  376:  DBusFreeFunction old_free_func;
        -:  377:  void *old_data;
        -:  378:  dbus_bool_t retval;
        -:  379:
    #####:  380:  _dbus_return_val_if_fail (pending != NULL, FALSE);
call    0 never executed
branch  1 never executed
branch  2 never executed
call    3 never executed
call    4 never executed
    #####:  381:  _dbus_return_val_if_fail (slot >= 0, FALSE);
call    0 never executed
branch  1 never executed
branch  2 never executed
call    3 never executed
call    4 never executed
        -:  382:
    #####:  383:  retval = _dbus_data_slot_list_set (&slot_allocator,
call    0 never executed
        -:  384:                                     &pending->slot_list,
        -:  385:                                     slot, data, free_data_func,
        -:  386:                                     &old_free_func, &old_data);
        -:  387:
    #####:  388:  if (retval)
branch  0 never executed
branch  1 never executed
        -:  389:    {
    #####:  390:      if (old_free_func)
branch  0 never executed
branch  1 never executed
    #####:  391:        (* old_free_func) (old_data);
call    0 never executed
        -:  392:    }
        -:  393:
    #####:  394:  return retval;
        -:  395:}
        -:  396:
        -:  397:/**
        -:  398: * Retrieves data previously set with dbus_pending_call_set_data().
        -:  399: * The slot must still be allocated (must not have been freed).
        -:  400: *
        -:  401: * @param pending the pending_call
        -:  402: * @param slot the slot to get data from
        -:  403: * @returns the data, or #NULL if not found
        -:  404: */
        -:  405:void*
        -:  406:dbus_pending_call_get_data (DBusPendingCall   *pending,
        -:  407:                            dbus_int32_t       slot)
function dbus_pending_call_get_data called 0 returned 0% blocks executed 0%
    #####:  408:{
        -:  409:  void *res;
        -:  410:
    #####:  411:  _dbus_return_val_if_fail (pending != NULL, NULL);
call    0 never executed
branch  1 never executed
branch  2 never executed
call    3 never executed
call    4 never executed
        -:  412:
    #####:  413:  res = _dbus_data_slot_list_get (&slot_allocator,
call    0 never executed
        -:  414:                                  &pending->slot_list,
        -:  415:                                  slot);
        -:  416:
    #####:  417:  return res;
        -:  418:}
        -:  419:
        -:  420:/** @} */
        -:  421:
        -:  422:#ifdef DBUS_BUILD_TESTS
        -:  423:
        -:  424:/**
        -:  425: * @ingroup DBusPendingCallInternals
        -:  426: * Unit test for DBusPendingCall.
        -:  427: *
        -:  428: * @returns #TRUE on success.
        -:  429: */
        -:  430:dbus_bool_t
        -:  431:_dbus_pending_call_test (const char *test_data_dir)
function _dbus_pending_call_test called 1 returned 100% blocks executed 100%
        1:  432:{  
        -:  433:
        1:  434:  return TRUE;
        -:  435:}
        -:  436:#endif /* DBUS_BUILD_TESTS */