closed #4106: Object which isn't in Vector would also be released when invoking Vector::eraseObject.

Also refactored 'Vector::eraseObject':
1) Removed 'toRelease' parameter, Vector class should manage reference count.
2) Added 'removeAll' parameter to decide wether to remove all elements with the same value or just the first occurrence .
3) Added relevant UnitTest for 'Vector::eraseObject'.
This commit is contained in:
James Chen 2014-02-21 11:24:37 +08:00
parent 2eb1c1bb73
commit c6b2b86fe5
3 changed files with 71 additions and 10 deletions

View File

@ -309,18 +309,38 @@ public:
last->release();
}
/** @brief Remove a certain object.
/** @brief Remove a certain object in Vector.
* @param object The object to be removed.
* @param toRelease Whether to decrease the referece count of the deleted object.
* @param removeAll Whether to remove all elements with the same value.
*/
void eraseObject(T object, bool toRelease = true)
void eraseObject(T object, bool removeAll = false)
{
CCASSERT(object != nullptr, "The object should not be nullptr");
auto iter = std::find(_data.begin(), _data.end(), object);
if (iter != _data.end())
_data.erase(iter);
if (toRelease)
object->release();
if (removeAll)
{
for (auto iter = _data.begin(); iter != _data.end();)
{
if ((*iter) == object)
{
iter = _data.erase(iter);
object->release();
}
else
{
++iter;
}
}
}
else
{
auto iter = std::find(_data.begin(), _data.end(), object);
if (iter != _data.end())
{
_data.erase(iter);
object->release();
}
}
}
/** @brief Removes from the vector with an iterator.

View File

@ -186,7 +186,7 @@ void Control::removeTargetWithActionForControlEvent(Ref* target, Handler action,
//remove all invocations if the target and action are null
//TODO: should the invocations be deleted, or just removed from the array? Won't that cause issues if you add a single invocation for multiple events?
bool bDeleteObjects=true;
if (!target && !action)
{
//remove objects
@ -215,7 +215,7 @@ void Control::removeTargetWithActionForControlEvent(Ref* target, Handler action,
}
for(const auto &invocation : tobeRemovedInvocations) {
eventInvocationList.eraseObject(invocation, bDeleteObjects);
eventInvocationList.eraseObject(invocation);
}
}
}

View File

@ -233,6 +233,47 @@ void TemplateVectorTest::onEnter()
vec6.eraseObject(vec6.at(2));
CCASSERT(vec6.at(2)->getTag() == 1013, "");
vec6.clear();
auto objA = Node::create(); // retain count is 1
auto objB = Node::create();
auto objC = Node::create();
{
Vector<Node*> array1;
Vector<Node*> array2;
// push back objA 3 times
array1.pushBack(objA); // retain count is 2
array1.pushBack(objA); // retain count is 3
array1.pushBack(objA); // retain count is 4
array2.pushBack(objA); // retain count is 5
array2.pushBack(objB);
array2.pushBack(objC);
for (auto obj : array1) {
array2.eraseObject(obj);
}
CCASSERT(objA->getReferenceCount() == 4, "");
}
CCASSERT(objA->getReferenceCount() == 1, "");
{
Vector<Node*> array1;
// push back objA 3 times
array1.pushBack(objA); // retain count is 2
array1.pushBack(objA); // retain count is 3
array1.pushBack(objA); // retain count is 4
CCASSERT(objA->getReferenceCount() == 4, "");
array1.eraseObject(objA, true); // Remove all occurrences in the Vector.
CCASSERT(objA->getReferenceCount() == 1, "");
array1.pushBack(objA); // retain count is 2
array1.pushBack(objA); // retain count is 3
array1.pushBack(objA); // retain count is 4
array1.eraseObject(objA, false);
CCASSERT(objA->getReferenceCount() == 3, ""); // Only remove the first occurrence in the Vector.
}
// Check the retain count in vec7
CCASSERT(vec7.size() == 20, "");