Coverage report for dbus/dbus-dataslot.c.gcov
-: 0:Source:dbus-dataslot.c
-: 0:Graph:.libs/dbus-dataslot.gcno
-: 0:Data:.libs/dbus-dataslot.gcda
-: 0:Runs:11819
-: 0:Programs:5
-: 1:/* -*- mode: C; c-file-style: "gnu" -*- */
-: 2:/* dbus-dataslot.c storing data on objects
-: 3: *
-: 4: * Copyright (C) 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:#include "dbus-dataslot.h"
-: 24:#include "dbus-threads-internal.h"
-: 25:
-: 26:/**
-: 27: * @defgroup DBusDataSlot Data slots
-: 28: * @ingroup DBusInternals
-: 29: * @brief Storing data by ID
-: 30: *
-: 31: * Types and functions related to storing data by an
-: 32: * allocated ID. This is used for dbus_connection_set_data(),
-: 33: * dbus_server_set_data(), etc.
-: 34: * @{
-: 35: */
-: 36:
-: 37:/**
-: 38: * Initializes a data slot allocator object, used to assign
-: 39: * integer IDs for data slots.
-: 40: *
-: 41: * @param allocator the allocator to initialize
-: 42: */
-: 43:dbus_bool_t
-: 44:_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator)
function _dbus_data_slot_allocator_init called 1 returned 100% blocks executed 100%
1: 45:{
1: 46: allocator->allocated_slots = NULL;
1: 47: allocator->n_allocated_slots = 0;
1: 48: allocator->n_used_slots = 0;
1: 49: allocator->lock = NULL;
-: 50:
1: 51: return TRUE;
-: 52:}
-: 53:
-: 54:/**
-: 55: * Allocates an integer ID to be used for storing data
-: 56: * in a #DBusDataSlotList. If the value at *slot_id_p is
-: 57: * not -1, this function just increments the refcount for
-: 58: * the existing slot ID. If the value is -1, a new slot ID
-: 59: * is allocated and stored at *slot_id_p.
-: 60: *
-: 61: * @param allocator the allocator
-: 62: * @param mutex the lock for this allocator
-: 63: * @param slot_id_p address to fill with the slot ID
-: 64: * @returns #TRUE on success
-: 65: */
-: 66:dbus_bool_t
-: 67:_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator,
-: 68: DBusMutex *mutex,
-: 69: dbus_int32_t *slot_id_p)
function _dbus_data_slot_allocator_alloc called 14920 returned 100% blocks executed 75%
14920: 70:{
-: 71: dbus_int32_t slot;
-: 72:
14920: 73: if (!_dbus_mutex_lock (mutex))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 74: return FALSE;
-: 75:
14920: 76: if (allocator->n_allocated_slots == 0)
branch 0 taken 15% (fallthrough)
branch 1 taken 85%
-: 77: {
2282: 78: _dbus_assert (allocator->lock == NULL);
call 0 returned 100%
2282: 79: allocator->lock = mutex;
-: 80: }
-: 81: else
12638: 82: _dbus_assert (allocator->lock == mutex);
call 0 returned 100%
-: 83:
14920: 84: if (*slot_id_p >= 0)
branch 0 taken 84% (fallthrough)
branch 1 taken 16%
-: 85: {
12537: 86: slot = *slot_id_p;
-: 87:
12537: 88: _dbus_assert (slot < allocator->n_allocated_slots);
call 0 returned 100%
12537: 89: _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
call 0 returned 100%
-: 90:
12537: 91: allocator->allocated_slots[slot].refcount += 1;
-: 92:
12537: 93: goto out;
-: 94: }
-: 95:
2383: 96: _dbus_assert (*slot_id_p < 0);
call 0 returned 100%
-: 97:
2383: 98: if (allocator->n_used_slots < allocator->n_allocated_slots)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
-: 99: {
#####: 100: slot = 0;
#####: 101: while (slot < allocator->n_allocated_slots)
branch 0 never executed
branch 1 never executed
-: 102: {
#####: 103: if (allocator->allocated_slots[slot].slot_id < 0)
branch 0 never executed
branch 1 never executed
-: 104: {
#####: 105: allocator->allocated_slots[slot].slot_id = slot;
#####: 106: allocator->allocated_slots[slot].refcount = 1;
#####: 107: allocator->n_used_slots += 1;
#####: 108: break;
-: 109: }
#####: 110: ++slot;
-: 111: }
-: 112:
#####: 113: _dbus_assert (slot < allocator->n_allocated_slots);
call 0 never executed
-: 114: }
-: 115: else
-: 116: {
-: 117: DBusAllocatedSlot *tmp;
-: 118:
2383: 119: slot = -1;
2383: 120: tmp = dbus_realloc (allocator->allocated_slots,
call 0 returned 100%
-: 121: sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1));
2383: 122: if (tmp == NULL)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 123: goto out;
-: 124:
2383: 125: allocator->allocated_slots = tmp;
2383: 126: slot = allocator->n_allocated_slots;
2383: 127: allocator->n_allocated_slots += 1;
2383: 128: allocator->n_used_slots += 1;
2383: 129: allocator->allocated_slots[slot].slot_id = slot;
2383: 130: allocator->allocated_slots[slot].refcount = 1;
-: 131: }
-: 132:
2383: 133: _dbus_assert (slot >= 0);
call 0 returned 100%
2383: 134: _dbus_assert (slot < allocator->n_allocated_slots);
call 0 returned 100%
2383: 135: _dbus_assert (*slot_id_p < 0);
call 0 returned 100%
2383: 136: _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
call 0 returned 100%
2383: 137: _dbus_assert (allocator->allocated_slots[slot].refcount == 1);
call 0 returned 100%
-: 138:
2383: 139: *slot_id_p = slot;
-: 140:
2383: 141: _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n",
call 0 returned 100%
-: 142: slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots);
-: 143:
14920: 144: out:
14920: 145: _dbus_mutex_unlock (allocator->lock);
call 0 returned 100%
14920: 146: return slot >= 0;
-: 147:}
-: 148:
-: 149:/**
-: 150: * Deallocates an ID previously allocated with
-: 151: * _dbus_data_slot_allocator_alloc(). Existing data stored on
-: 152: * existing #DBusDataList objects with this ID will be freed when the
-: 153: * data list is finalized, but may not be retrieved (and may only be
-: 154: * replaced if someone else reallocates the slot).
-: 155: * The slot value is reset to -1 if this is the last unref.
-: 156: *
-: 157: * @param allocator the allocator
-: 158: * @param slot_id_p address where we store the slot
-: 159: */
-: 160:void
-: 161:_dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator,
-: 162: dbus_int32_t *slot_id_p)
function _dbus_data_slot_allocator_free called 14503 returned 100% blocks executed 100%
14503: 163:{
14503: 164: _dbus_mutex_lock (allocator->lock);
call 0 returned 100%
-: 165:
14503: 166: _dbus_assert (*slot_id_p < allocator->n_allocated_slots);
call 0 returned 100%
14503: 167: _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p);
call 0 returned 100%
14503: 168: _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0);
call 0 returned 100%
-: 169:
14503: 170: allocator->allocated_slots[*slot_id_p].refcount -= 1;
-: 171:
14503: 172: if (allocator->allocated_slots[*slot_id_p].refcount > 0)
branch 0 taken 86% (fallthrough)
branch 1 taken 14%
-: 173: {
12537: 174: _dbus_mutex_unlock (allocator->lock);
call 0 returned 100%
12537: 175: return;
-: 176: }
-: 177:
-: 178: /* refcount is 0, free the slot */
1966: 179: _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n",
call 0 returned 100%
-: 180: *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots);
-: 181:
1966: 182: allocator->allocated_slots[*slot_id_p].slot_id = -1;
1966: 183: *slot_id_p = -1;
-: 184:
1966: 185: allocator->n_used_slots -= 1;
-: 186:
1966: 187: if (allocator->n_used_slots == 0)
branch 0 taken 95% (fallthrough)
branch 1 taken 5%
-: 188: {
1865: 189: DBusMutex *mutex = allocator->lock;
-: 190:
1865: 191: dbus_free (allocator->allocated_slots);
call 0 returned 100%
1865: 192: allocator->allocated_slots = NULL;
1865: 193: allocator->n_allocated_slots = 0;
1865: 194: allocator->lock = NULL;
-: 195:
1865: 196: _dbus_mutex_unlock (mutex);
call 0 returned 100%
-: 197: }
-: 198: else
-: 199: {
101: 200: _dbus_mutex_unlock (allocator->lock);
call 0 returned 100%
-: 201: }
-: 202:}
-: 203:
-: 204:/**
-: 205: * Initializes a slot list.
-: 206: * @param list the list to initialize.
-: 207: */
-: 208:void
-: 209:_dbus_data_slot_list_init (DBusDataSlotList *list)
function _dbus_data_slot_list_init called 38370 returned 100% blocks executed 100%
38370: 210:{
38370: 211: list->slots = NULL;
38370: 212: list->n_slots = 0;
38370: 213:}
-: 214:
-: 215:/**
-: 216: * Stores a pointer in the data slot list, along with an optional
-: 217: * function to be used for freeing the data when the data is set
-: 218: * again, or when the slot list is finalized. The slot number must
-: 219: * have been allocated with _dbus_data_slot_allocator_alloc() for the
-: 220: * same allocator passed in here. The same allocator has to be used
-: 221: * with the slot list every time.
-: 222: *
-: 223: * @param allocator the allocator to use
-: 224: * @param list the data slot list
-: 225: * @param slot the slot number
-: 226: * @param data the data to store
-: 227: * @param free_data_func finalizer function for the data
-: 228: * @param old_free_func free function for any previously-existing data
-: 229: * @param old_data previously-existing data, should be freed with old_free_func
-: 230: * @returns #TRUE if there was enough memory to store the data
-: 231: */
-: 232:dbus_bool_t
-: 233:_dbus_data_slot_list_set (DBusDataSlotAllocator *allocator,
-: 234: DBusDataSlotList *list,
-: 235: int slot,
-: 236: void *data,
-: 237: DBusFreeFunction free_data_func,
-: 238: DBusFreeFunction *old_free_func,
-: 239: void **old_data)
function _dbus_data_slot_list_set called 22310 returned 100% blocks executed 94%
22310: 240:{
-: 241:#ifndef DBUS_DISABLE_ASSERT
-: 242: /* We need to take the allocator lock here, because the allocator could
-: 243: * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
-: 244: * are disabled, since then the asserts are empty.
-: 245: */
22310: 246: if (!_dbus_mutex_lock (allocator->lock))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 247: return FALSE;
22310: 248: _dbus_assert (slot < allocator->n_allocated_slots);
call 0 returned 100%
22310: 249: _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
call 0 returned 100%
22310: 250: _dbus_mutex_unlock (allocator->lock);
call 0 returned 100%
-: 251:#endif
-: 252:
22310: 253: if (slot >= list->n_slots)
branch 0 taken 64% (fallthrough)
branch 1 taken 36%
-: 254: {
-: 255: DBusDataSlot *tmp;
-: 256: int i;
-: 257:
14326: 258: tmp = dbus_realloc (list->slots,
call 0 returned 100%
-: 259: sizeof (DBusDataSlot) * (slot + 1));
14326: 260: if (tmp == NULL)
branch 0 taken 1% (fallthrough)
branch 1 taken 99%
13: 261: return FALSE;
-: 262:
14313: 263: list->slots = tmp;
14313: 264: i = list->n_slots;
14313: 265: list->n_slots = slot + 1;
48334: 266: while (i < list->n_slots)
branch 0 taken 58%
branch 1 taken 42% (fallthrough)
-: 267: {
19708: 268: list->slots[i].data = NULL;
19708: 269: list->slots[i].free_data_func = NULL;
19708: 270: ++i;
-: 271: }
-: 272: }
-: 273:
22297: 274: _dbus_assert (slot < list->n_slots);
call 0 returned 100%
-: 275:
22297: 276: *old_data = list->slots[slot].data;
22297: 277: *old_free_func = list->slots[slot].free_data_func;
-: 278:
22297: 279: list->slots[slot].data = data;
22297: 280: list->slots[slot].free_data_func = free_data_func;
-: 281:
22297: 282: return TRUE;
-: 283:}
-: 284:
-: 285:/**
-: 286: * Retrieves data previously set with _dbus_data_slot_list_set_data().
-: 287: * The slot must still be allocated (must not have been freed).
-: 288: *
-: 289: * @param allocator the allocator slot was allocated from
-: 290: * @param list the data slot list
-: 291: * @param slot the slot to get data from
-: 292: * @returns the data, or #NULL if not found
-: 293: */
-: 294:void*
-: 295:_dbus_data_slot_list_get (DBusDataSlotAllocator *allocator,
-: 296: DBusDataSlotList *list,
-: 297: int slot)
function _dbus_data_slot_list_get called 871388 returned 100% blocks executed 91%
871388: 298:{
-: 299:#ifndef DBUS_DISABLE_ASSERT
-: 300: /* We need to take the allocator lock here, because the allocator could
-: 301: * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts
-: 302: * are disabled, since then the asserts are empty.
-: 303: */
871388: 304: if (!_dbus_mutex_lock (allocator->lock))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 305: return FALSE;
871388: 306: _dbus_assert (slot >= 0);
call 0 returned 100%
871388: 307: _dbus_assert (slot < allocator->n_allocated_slots);
call 0 returned 100%
871388: 308: _dbus_assert (allocator->allocated_slots[slot].slot_id == slot);
call 0 returned 100%
871388: 309: _dbus_mutex_unlock (allocator->lock);
call 0 returned 100%
-: 310:#endif
-: 311:
871388: 312: if (slot >= list->n_slots)
branch 0 taken 1% (fallthrough)
branch 1 taken 99%
6345: 313: return NULL;
-: 314: else
865043: 315: return list->slots[slot].data;
-: 316:}
-: 317:
-: 318:/**
-: 319: * Frees all data slots contained in the list, calling
-: 320: * application-provided free functions if they exist.
-: 321: *
-: 322: * @param list the list to clear
-: 323: */
-: 324:void
-: 325:_dbus_data_slot_list_clear (DBusDataSlotList *list)
function _dbus_data_slot_list_clear called 392563 returned 100% blocks executed 100%
392563: 326:{
-: 327: int i;
-: 328:
392563: 329: i = 0;
804417: 330: while (i < list->n_slots)
branch 0 taken 5%
branch 1 taken 95% (fallthrough)
-: 331: {
19291: 332: if (list->slots[i].free_data_func)
branch 0 taken 31% (fallthrough)
branch 1 taken 69%
6012: 333: (* list->slots[i].free_data_func) (list->slots[i].data);
call 0 returned 100%
19291: 334: list->slots[i].data = NULL;
19291: 335: list->slots[i].free_data_func = NULL;
19291: 336: ++i;
-: 337: }
392563: 338:}
-: 339:
-: 340:/**
-: 341: * Frees the data slot list and all data slots contained
-: 342: * in it, calling application-provided free functions
-: 343: * if they exist.
-: 344: *
-: 345: * @param list the list to free
-: 346: */
-: 347:void
-: 348:_dbus_data_slot_list_free (DBusDataSlotList *list)
function _dbus_data_slot_list_free called 33863 returned 100% blocks executed 100%
33863: 349:{
33863: 350: _dbus_data_slot_list_clear (list);
call 0 returned 100%
-: 351:
33863: 352: dbus_free (list->slots);
call 0 returned 100%
33863: 353: list->slots = NULL;
33863: 354: list->n_slots = 0;
33863: 355:}
-: 356:
-: 357:/** @} */
-: 358:
-: 359:#ifdef DBUS_BUILD_TESTS
-: 360:#include "dbus-test.h"
-: 361:#include <stdio.h>
-: 362:
-: 363:static int free_counter;
-: 364:
-: 365:static void
-: 366:test_free_slot_data_func (void *data)
function test_free_slot_data_func called 200 returned 100% blocks executed 100%
200: 367:{
200: 368: int i = _DBUS_POINTER_TO_INT (data);
-: 369:
200: 370: _dbus_assert (free_counter == i);
call 0 returned 100%
200: 371: ++free_counter;
200: 372:}
-: 373:
-: 374:/**
-: 375: * Test function for data slots
-: 376: */
-: 377:dbus_bool_t
-: 378:_dbus_data_slot_test (void)
function _dbus_data_slot_test called 1 returned 100% blocks executed 89%
1: 379:{
-: 380: DBusDataSlotAllocator allocator;
-: 381: DBusDataSlotList list;
-: 382: int i;
-: 383: DBusFreeFunction old_free_func;
-: 384: void *old_data;
-: 385: DBusMutex *mutex;
-: 386:
1: 387: if (!_dbus_data_slot_allocator_init (&allocator))
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
#####: 388: _dbus_assert_not_reached ("no memory for allocator");
call 0 never executed
-: 389:
1: 390: _dbus_data_slot_list_init (&list);
call 0 returned 100%
-: 391:
1: 392: mutex = _dbus_mutex_new ();
call 0 returned 100%
1: 393: if (mutex == NULL)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 394: _dbus_assert_not_reached ("failed to alloc mutex");
call 0 never executed
-: 395:
-: 396:#define N_SLOTS 100
-: 397:
1: 398: i = 0;
102: 399: while (i < N_SLOTS)
branch 0 taken 99%
branch 1 taken 1% (fallthrough)
-: 400: {
-: 401: /* we don't really want apps to rely on this ordered
-: 402: * allocation, but it simplifies things to rely on it
-: 403: * here.
-: 404: */
100: 405: dbus_int32_t tmp = -1;
-: 406:
100: 407: _dbus_data_slot_allocator_alloc (&allocator, mutex, &tmp);
call 0 returned 100%
-: 408:
100: 409: if (tmp != i)
branch 0 taken 0% (fallthrough)
branch 1 taken 100%
#####: 410: _dbus_assert_not_reached ("did not allocate slots in numeric order\n");
call 0 never executed
-: 411:
100: 412: ++i;
-: 413: }
-: 414:
1: 415: i = 0;
102: 416: while (i < N_SLOTS)
branch 0 taken 99%
branch 1 taken 1% (fallthrough)
-: 417: {
100: 418: if (!_dbus_data_slot_list_set (&allocator, &list,
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 419: i,
-: 420: _DBUS_INT_TO_POINTER (i),
-: 421: test_free_slot_data_func,
-: 422: &old_free_func, &old_data))
#####: 423: _dbus_assert_not_reached ("no memory to set data");
call 0 never executed
-: 424:
100: 425: _dbus_assert (old_free_func == NULL);
call 0 returned 100%
100: 426: _dbus_assert (old_data == NULL);
call 0 returned 100%
-: 427:
100: 428: _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
call 0 returned 100%
call 1 returned 100%
-: 429: _DBUS_INT_TO_POINTER (i));
-: 430:
100: 431: ++i;
-: 432: }
-: 433:
1: 434: free_counter = 0;
1: 435: i = 0;
102: 436: while (i < N_SLOTS)
branch 0 taken 99%
branch 1 taken 1% (fallthrough)
-: 437: {
100: 438: if (!_dbus_data_slot_list_set (&allocator, &list,
call 0 returned 100%
branch 1 taken 0% (fallthrough)
branch 2 taken 100%
-: 439: i,
-: 440: _DBUS_INT_TO_POINTER (i),
-: 441: test_free_slot_data_func,
-: 442: &old_free_func, &old_data))
#####: 443: _dbus_assert_not_reached ("no memory to set data");
call 0 never executed
-: 444:
100: 445: _dbus_assert (old_free_func == test_free_slot_data_func);
call 0 returned 100%
100: 446: _dbus_assert (_DBUS_POINTER_TO_INT (old_data) == i);
call 0 returned 100%
-: 447:
100: 448: (* old_free_func) (old_data);
call 0 returned 100%
100: 449: _dbus_assert (i == (free_counter - 1));
call 0 returned 100%
-: 450:
100: 451: _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) ==
call 0 returned 100%
call 1 returned 100%
-: 452: _DBUS_INT_TO_POINTER (i));
-: 453:
100: 454: ++i;
-: 455: }
-: 456:
1: 457: free_counter = 0;
1: 458: _dbus_data_slot_list_free (&list);
call 0 returned 100%
-: 459:
1: 460: _dbus_assert (N_SLOTS == free_counter);
call 0 returned 100%
-: 461:
1: 462: i = 0;
102: 463: while (i < N_SLOTS)
branch 0 taken 99%
branch 1 taken 1% (fallthrough)
-: 464: {
100: 465: dbus_int32_t tmp = i;
-: 466:
100: 467: _dbus_data_slot_allocator_free (&allocator, &tmp);
call 0 returned 100%
100: 468: _dbus_assert (tmp == -1);
call 0 returned 100%
100: 469: ++i;
-: 470: }
-: 471:
1: 472: _dbus_mutex_free (mutex);
call 0 returned 100%
-: 473:
1: 474: return TRUE;
-: 475:}
-: 476:
-: 477:#endif /* DBUS_BUILD_TESTS */