X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-dataslot.c;h=e37c9dd5f7801138513a7eedc04b68c9016eb613;hb=82600c61dcb715e1651faaa4b5e577fca90bc35d;hp=46e2bfc13f7e21d9a28f7556b7ec99a31d9e915b;hpb=f7c24715b5489b28b47499eb252b941b735fa1bc;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c index 46e2bfc..e37c9dd 100644 --- a/dbus/dbus-dataslot.c +++ b/dbus/dbus-dataslot.c @@ -1,9 +1,9 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-dataslot.c storing data on objects * * Copyright (C) 2003 Red Hat, Inc. * - * Licensed under the Academic Free License version 1.2 + * Licensed under the Academic Free License version 2.1 * * 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 @@ -17,11 +17,13 @@ * * 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-dataslot.h" -#include "dbus-threads.h" +#include "dbus-threads-internal.h" /** * @defgroup DBusDataSlot Data slots @@ -41,45 +43,60 @@ * @param allocator the allocator to initialize */ dbus_bool_t -_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) +_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator, + DBusGlobalLock lock) { allocator->allocated_slots = NULL; allocator->n_allocated_slots = 0; allocator->n_used_slots = 0; - allocator->lock = dbus_mutex_new (); - if (allocator->lock == NULL) - return FALSE; - else - return TRUE; + allocator->lock = lock; + + return TRUE; } /** * Allocates an integer ID to be used for storing data - * in a #DBusDataSlotList. - * - * @todo all over the code we have foo_slot and foo_slot_refcount, - * would be better to add an interface for that to - * DBusDataSlotAllocator so it isn't cut-and-pasted everywhere. + * in a #DBusDataSlotList. If the value at *slot_id_p is + * not -1, this function just increments the refcount for + * the existing slot ID. If the value is -1, a new slot ID + * is allocated and stored at *slot_id_p. * * @param allocator the allocator - * @returns the integer ID, or -1 on failure + * @param slot_id_p address to fill with the slot ID + * @returns #TRUE on success */ -int -_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator) +dbus_bool_t +_dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, + dbus_int32_t *slot_id_p) { - int slot; - - if (!dbus_mutex_lock (allocator->lock)) - return -1; + dbus_int32_t slot; + + if (!_dbus_lock (allocator->lock)) + return FALSE; + + if (*slot_id_p >= 0) + { + slot = *slot_id_p; + + _dbus_assert (slot < allocator->n_allocated_slots); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + + allocator->allocated_slots[slot].refcount += 1; + goto out; + } + + _dbus_assert (*slot_id_p < 0); + if (allocator->n_used_slots < allocator->n_allocated_slots) { slot = 0; while (slot < allocator->n_allocated_slots) { - if (allocator->allocated_slots[slot] < 0) + if (allocator->allocated_slots[slot].slot_id < 0) { - allocator->allocated_slots[slot] = slot; + allocator->allocated_slots[slot].slot_id = slot; + allocator->allocated_slots[slot].refcount = 1; allocator->n_used_slots += 1; break; } @@ -90,11 +107,11 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator) } else { - int *tmp; + DBusAllocatedSlot *tmp; slot = -1; tmp = dbus_realloc (allocator->allocated_slots, - sizeof (int) * (allocator->n_allocated_slots + 1)); + sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1)); if (tmp == NULL) goto out; @@ -102,42 +119,66 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator) slot = allocator->n_allocated_slots; allocator->n_allocated_slots += 1; allocator->n_used_slots += 1; - allocator->allocated_slots[slot] = slot; + allocator->allocated_slots[slot].slot_id = slot; + allocator->allocated_slots[slot].refcount = 1; } _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); - + _dbus_assert (*slot_id_p < 0); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + _dbus_assert (allocator->allocated_slots[slot].refcount == 1); + + *slot_id_p = slot; + _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n", slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); out: - dbus_mutex_unlock (allocator->lock); - return slot; + _dbus_unlock (allocator->lock); + return slot >= 0; } /** * Deallocates an ID previously allocated with * _dbus_data_slot_allocator_alloc(). Existing data stored on - * existing #DBusDataList objects with this ID will be freed when the + * existing #DBusDataSlotList objects with this ID will be freed when the * data list is finalized, but may not be retrieved (and may only be * replaced if someone else reallocates the slot). + * The slot value is reset to -1 if this is the last unref. * * @param allocator the allocator - * @param slot the slot to deallocate + * @param slot_id_p address where we store the slot */ void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, - int slot) + dbus_int32_t *slot_id_p) { - dbus_mutex_lock (allocator->lock); + if (!_dbus_lock (allocator->lock)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated this slot"); - _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (*slot_id_p < allocator->n_allocated_slots); + _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p); + _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0); + + allocator->allocated_slots[*slot_id_p].refcount -= 1; + + if (allocator->allocated_slots[*slot_id_p].refcount > 0) + { + _dbus_unlock (allocator->lock); + return; + } + + /* refcount is 0, free the slot */ + _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n", + *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots); + + allocator->allocated_slots[*slot_id_p].slot_id = -1; + *slot_id_p = -1; - allocator->allocated_slots[slot] = -1; allocator->n_used_slots -= 1; - + if (allocator->n_used_slots == 0) { dbus_free (allocator->allocated_slots); @@ -145,10 +186,7 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, allocator->n_allocated_slots = 0; } - _dbus_verbose ("Freed slot %d on allocator %p total %d allocated %d used\n", - slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); - - dbus_mutex_unlock (allocator->lock); + _dbus_unlock (allocator->lock); } /** @@ -193,11 +231,13 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts * are disabled, since then the asserts are empty. */ - if (!dbus_mutex_lock (allocator->lock)) - return FALSE; + if (!_dbus_lock (allocator->lock)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated this slot"); + _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); - dbus_mutex_unlock (allocator->lock); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + _dbus_unlock (allocator->lock); #endif if (slot >= list->n_slots) @@ -251,12 +291,14 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator, * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts * are disabled, since then the asserts are empty. */ - if (!dbus_mutex_lock (allocator->lock)) - return FALSE; + if (!_dbus_lock (allocator->lock)) + _dbus_assert_not_reached ("we should have initialized global locks " + "before we allocated this slot"); + _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); - dbus_mutex_unlock (allocator->lock); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + _dbus_unlock (allocator->lock); #endif if (slot >= list->n_slots) @@ -266,14 +308,13 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator, } /** - * Frees the data slot list and all data slots contained - * in it, calling application-provided free functions - * if they exist. + * Frees all data slots contained in the list, calling + * application-provided free functions if they exist. * - * @param list the list to free + * @param list the list to clear */ void -_dbus_data_slot_list_free (DBusDataSlotList *list) +_dbus_data_slot_list_clear (DBusDataSlotList *list) { int i; @@ -286,7 +327,20 @@ _dbus_data_slot_list_free (DBusDataSlotList *list) list->slots[i].free_data_func = NULL; ++i; } +} +/** + * Frees the data slot list and all data slots contained + * in it, calling application-provided free functions + * if they exist. + * + * @param list the list to free + */ +void +_dbus_data_slot_list_free (DBusDataSlotList *list) +{ + _dbus_data_slot_list_clear (list); + dbus_free (list->slots); list->slots = NULL; list->n_slots = 0; @@ -294,7 +348,7 @@ _dbus_data_slot_list_free (DBusDataSlotList *list) /** @} */ -#ifdef DBUS_BUILD_TESTS +#ifdef DBUS_ENABLE_EMBEDDED_TESTS #include "dbus-test.h" #include @@ -320,8 +374,8 @@ _dbus_data_slot_test (void) int i; DBusFreeFunction old_free_func; void *old_data; - - if (!_dbus_data_slot_allocator_init (&allocator)) + + if (!_dbus_data_slot_allocator_init (&allocator, _DBUS_LOCK_server_slots)) _dbus_assert_not_reached ("no memory for allocator"); _dbus_data_slot_list_init (&list); @@ -335,7 +389,11 @@ _dbus_data_slot_test (void) * allocation, but it simplifies things to rely on it * here. */ - if (_dbus_data_slot_allocator_alloc (&allocator) != i) + dbus_int32_t tmp = -1; + + _dbus_data_slot_allocator_alloc (&allocator, &tmp); + + if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); ++i; @@ -391,11 +449,14 @@ _dbus_data_slot_test (void) i = 0; while (i < N_SLOTS) { - _dbus_data_slot_allocator_free (&allocator, i); + dbus_int32_t tmp = i; + + _dbus_data_slot_allocator_free (&allocator, &tmp); + _dbus_assert (tmp == -1); ++i; } - + return TRUE; } -#endif /* DBUS_BUILD_TESTS */ +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */