/** * Stores a pointer on a DBusServer, along * with an optional function to be used for freeing * the data when the data is set again, or when * the server is finalized. The slot number * must have been allocated with dbus_server_allocate_data_slot(). * * @param server the server * @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_server_set_data (DBusServer *server, int slot, void *data, DBusFreeFunction free_data_func) { DBusFreeFunction old_free_func; void *old_data; dbus_bool_t retval; _dbus_return_val_if_fail (server != NULL, FALSE); SERVER_LOCK (server); retval = _dbus_data_slot_list_set (&slot_allocator, &server->slot_list, slot, data, free_data_func, &old_free_func, &old_data); SERVER_UNLOCK (server); if (retval) { /* Do the actual free outside the server lock */ if (old_free_func) (* old_free_func) (old_data); } 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_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; }
dbus_bool_t _dbus_data_slot_test (void) { DBusDataSlotAllocator allocator; DBusDataSlotList list; int i; DBusFreeFunction old_free_func; void *old_data; DBusMutex *mutex; if (!_dbus_data_slot_allocator_init (&allocator)) _dbus_assert_not_reached ("no memory for allocator"); _dbus_data_slot_list_init (&list); _dbus_mutex_new_at_location (&mutex); if (mutex == NULL) _dbus_assert_not_reached ("failed to alloc mutex"); #define N_SLOTS 100 i = 0; while (i < N_SLOTS) { /* we don't really want apps to rely on this ordered * allocation, but it simplifies things to rely on it * here. */ dbus_int32_t tmp = -1; _dbus_data_slot_allocator_alloc (&allocator, &mutex, &tmp); if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); ++i; } i = 0; while (i < N_SLOTS) { if (!_dbus_data_slot_list_set (&allocator, &list, i, _DBUS_INT_TO_POINTER (i), test_free_slot_data_func, &old_free_func, &old_data)) _dbus_assert_not_reached ("no memory to set data"); _dbus_assert (old_free_func == NULL); _dbus_assert (old_data == NULL); _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) == _DBUS_INT_TO_POINTER (i)); ++i; } free_counter = 0; i = 0; while (i < N_SLOTS) { if (!_dbus_data_slot_list_set (&allocator, &list, i, _DBUS_INT_TO_POINTER (i), test_free_slot_data_func, &old_free_func, &old_data)) _dbus_assert_not_reached ("no memory to set data"); _dbus_assert (old_free_func == test_free_slot_data_func); _dbus_assert (_DBUS_POINTER_TO_INT (old_data) == i); (* old_free_func) (old_data); _dbus_assert (i == (free_counter - 1)); _dbus_assert (_dbus_data_slot_list_get (&allocator, &list, i) == _DBUS_INT_TO_POINTER (i)); ++i; } free_counter = 0; _dbus_data_slot_list_free (&list); _dbus_assert (N_SLOTS == free_counter); i = 0; while (i < N_SLOTS) { dbus_int32_t tmp = i; _dbus_data_slot_allocator_free (&allocator, &tmp); _dbus_assert (tmp == -1); ++i; } _dbus_mutex_free_at_location (&mutex); return TRUE; }