char *test_deleteHashElement_single() { // simple hash function struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); int index = getHashIndex(hash, "G"); struct hashElement *element = findHashElementByKey(hash, "GREEN"); mu_assert("unexpected element at in single bucket list.", hash->elements[index] == element); mu_assert("Delete function did not remove single bucket element.", deleteHashElement(hash, "GREEN") == 0); mu_assert("Single element not deleted.", hash->elements[index] == NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); //normal hash function hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); index = getHashIndex(hash, "G"); element = findHashElementByKey(hash, "GREEN"); mu_assert("unexpected element at in single bucket list.", hash->elements[index] == element); mu_assert("Delete function did not remove single bucket element.", deleteHashElement(hash, "GREEN") == 0); mu_assert("Single element not deleted.", hash->elements[index] == NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
void CCActionManager::removeActionAtIndex(unsigned int uIndex, tHashElement *pElement) { CCAction *pAction = (CCAction*)pElement->actions->arr[uIndex]; if (pAction == pElement->currentAction && (! pElement->currentActionSalvaged)) { pElement->currentAction->retain(); pElement->currentActionSalvaged = true; } ccArrayRemoveObjectAtIndex(pElement->actions, uIndex, true); // update actionIndex in case we are in tick. looping over the actions if (pElement->actionIndex >= uIndex) { pElement->actionIndex--; } if (pElement->actions->num == 0) { if (m_pCurrentTarget == pElement) { m_bCurrentTargetSalvaged = true; } else { deleteHashElement(pElement); } } }
void CCActionManager::removeAllActionsFromTarget(CAObject *pTarget) { // explicit null handling if (pTarget == NULL) { return; } tHashElement *pElement = NULL; HASH_FIND_INT(m_pTargets, &pTarget, pElement); if (pElement) { if (ccArrayContainsObject(pElement->actions, pElement->currentAction) && (! pElement->currentActionSalvaged)) { pElement->currentAction->retain(); pElement->currentActionSalvaged = true; } ccArrayRemoveAllObjects(pElement->actions); if (m_pCurrentTarget == pElement) { m_bCurrentTargetSalvaged = true; } else { deleteHashElement(pElement); } } else { // CCLOG("CrossApp: removeAllActionsFromTarget: Target not found"); } }
//can't test on normal hash function. can't find collisons char *test_deleteHashElement_end() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); struct hashElement *element = findHashElementByKey(hash, "bbbb"); struct hashElement *newTail = element->prev; mu_assert("unexpected element at end of list.", element->next == NULL); mu_assert("Delete function did not remove end element.", deleteHashElement(hash, "bbbb") == 0); mu_assert("End element not deleted.", newTail->next == NULL); mu_assert("Did not delete end of list propertly.", newTail->prev != NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_deleteHashElement_middle() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); struct hashElement *element = findHashElementByKey(hash, "bbb"); struct hashElement *head = findHashElementByKey(hash, "bb"); struct hashElement *tail = findHashElementByKey(hash, "bbbb"); mu_assert("unexpected element after head.", head->next == element); mu_assert("unexpected element before tail.", tail->prev == element); mu_assert("Delete function did not remove middle element.", deleteHashElement(hash, "bbb") == 0); mu_assert("Did not reset next in list propertly.", head->next == tail); mu_assert("Did not reset prev in list propertly", tail->prev == head); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
//can't test on normal hash function. can't find collisons char *test_deleteHashElement_begining() { struct Symbol *symbol = calloc(1, sizeof(struct Symbol)); struct hash *hash = createHash(&getHashedKeySimple); mu_assert("Call to createHash does not seg fault.", 1); createHashElement(hash, "GREEN", symbol); createHashElement(hash, "bb", symbol); createHashElement(hash, "bbb", symbol); createHashElement(hash, "bbbb", symbol); struct hashElement *element = findHashElementByKey(hash, "bb"); struct hashElement *newHead = element->next; int index = getHashIndex(hash, "b"); mu_assert("unexpected element at head of bucket list.", hash->elements[index] == element); mu_assert("Delete function did not remove begining element.", deleteHashElement(hash, "bb") == 0); mu_assert("Begining element not deleted.", hash->elements[index] == newHead); mu_assert("Did not delete front of list propertly.", newHead->prev == NULL); mu_assert("Resulting bucket should have more than one element.", newHead->next != NULL); destroyHash(&hash); mu_assert("Call to destroyHash does not seg fault.", 1); return NULL; }
void ActionManager::removeActionAtIndex(ssize_t index, tHashElement *element) { Action *action = (Action*)element->actions->arr[index]; if (action == element->currentAction && (! element->currentActionSalvaged)) { element->currentAction->retain(); element->currentActionSalvaged = true; } ccArrayRemoveObjectAtIndex(element->actions, index, true); // update actionIndex in case we are in tick. looping over the actions if (element->actionIndex >= index) { element->actionIndex--; } if (element->actions->num == 0) { if (_currentTarget == element) { _currentTargetSalvaged = true; } else { deleteHashElement(element); } } }
void ActionManager::removeAllActionsFromTarget(Node *target) { // explicit null handling if (target == nullptr) { return; } tHashElement *element = nullptr; HASH_FIND_PTR(_targets, &target, element); if (element) { if (ccArrayContainsObject(element->actions, element->currentAction) && (! element->currentActionSalvaged)) { element->currentAction->retain(); element->currentActionSalvaged = true; } ccArrayRemoveAllObjects(element->actions); if (_currentTarget == element) { _currentTargetSalvaged = true; } else { deleteHashElement(element); } } }
void ActionManager::removeAllActionsFromTarget(Object *target) { // explicit null handling if (target == NULL) { return; } tHashElement *element = NULL; HASH_FIND_PTR(m_pTargets, &target, element); if (element) { if (ccArrayContainsObject(element->actions, element->currentAction) && (! element->currentActionSalvaged)) { element->currentAction->retain(); element->currentActionSalvaged = true; } ccArrayRemoveAllObjects(element->actions); if (m_pCurrentTarget == element) { m_bCurrentTargetSalvaged = true; } else { deleteHashElement(element); } } else { // CCLOG("cocos2d: removeAllActionsFromTarget: Target not found"); } }
// main loop void CCActionManager::update(float dt) { dt = 1/60.0f; for (tHashElement *elt = m_pTargets; elt != NULL; ) { m_pCurrentTarget = elt; m_bCurrentTargetSalvaged = false; if (! m_pCurrentTarget->paused) { // The 'actions' CCMutableArray may change while inside this loop. for (m_pCurrentTarget->actionIndex = 0; m_pCurrentTarget->actionIndex < m_pCurrentTarget->actions->num; m_pCurrentTarget->actionIndex++) { m_pCurrentTarget->currentAction = (CCAction*)m_pCurrentTarget->actions->arr[m_pCurrentTarget->actionIndex]; if (m_pCurrentTarget->currentAction == NULL) { continue; } m_pCurrentTarget->currentActionSalvaged = false; m_pCurrentTarget->currentAction->step(dt); if (m_pCurrentTarget->currentActionSalvaged) { // The currentAction told the node to remove it. To prevent the action from // accidentally deallocating itself before finishing its step, we retained // it. Now that step is done, it's safe to release it. m_pCurrentTarget->currentAction->release(); } else if (m_pCurrentTarget->currentAction->isDone()) { m_pCurrentTarget->currentAction->stop(); CCAction *pAction = m_pCurrentTarget->currentAction; // Make currentAction nil to prevent removeAction from salvaging it. m_pCurrentTarget->currentAction = NULL; removeAction(pAction); } m_pCurrentTarget->currentAction = NULL; } } // elt, at this moment, is still valid // so it is safe to ask this here (issue #490) elt = (tHashElement*)(elt->hh.next); // only delete currentTarget if no actions were scheduled during the cycle (issue #481) if (m_bCurrentTargetSalvaged && m_pCurrentTarget->actions->num == 0) { deleteHashElement(m_pCurrentTarget); } } // issue #635 m_pCurrentTarget = NULL; }
// main loop void ActionManager::update(float dt) { for (tHashElement *elt = _targets; elt != nullptr; ) { _currentTarget = elt; _currentTargetSalvaged = false; if (! _currentTarget->paused) { // The 'actions' MutableArray may change while inside this loop. for (_currentTarget->actionIndex = 0; _currentTarget->actionIndex < _currentTarget->actions->num; _currentTarget->actionIndex++) { _currentTarget->currentAction = (Action*)_currentTarget->actions->arr[_currentTarget->actionIndex]; if (_currentTarget->currentAction == nullptr) { continue; } _currentTarget->currentActionSalvaged = false; _currentTarget->currentAction->step(dt); if (_currentTarget->currentActionSalvaged) { // The currentAction told the node to remove it. To prevent the action from // accidentally deallocating itself before finishing its step, we retained // it. Now that step is done, it's safe to release it. _currentTarget->currentAction->release(); } else if (_currentTarget->currentAction->isDone()) { _currentTarget->currentAction->stop(); Action *action = _currentTarget->currentAction; // Make currentAction nil to prevent removeAction from salvaging it. _currentTarget->currentAction = nullptr; removeAction(action); } _currentTarget->currentAction = nullptr; } } // elt, at this moment, is still valid // so it is safe to ask this here (issue #490) elt = (tHashElement*)(elt->hh.next); // only delete currentTarget if no actions were scheduled during the cycle (issue #481) if (_currentTargetSalvaged && _currentTarget->actions->num == 0) { deleteHashElement(_currentTarget); } } // issue #635 _currentTarget = nullptr; }