mirror of https://github.com/axmolengine/axmol.git
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:
parent
2eb1c1bb73
commit
c6b2b86fe5
|
@ -309,18 +309,38 @@ public:
|
||||||
last->release();
|
last->release();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Remove a certain object.
|
/** @brief Remove a certain object in Vector.
|
||||||
* @param object The object to be removed.
|
* @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");
|
CCASSERT(object != nullptr, "The object should not be nullptr");
|
||||||
auto iter = std::find(_data.begin(), _data.end(), object);
|
|
||||||
if (iter != _data.end())
|
if (removeAll)
|
||||||
_data.erase(iter);
|
{
|
||||||
if (toRelease)
|
for (auto iter = _data.begin(); iter != _data.end();)
|
||||||
object->release();
|
{
|
||||||
|
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.
|
/** @brief Removes from the vector with an iterator.
|
||||||
|
|
|
@ -186,7 +186,7 @@ void Control::removeTargetWithActionForControlEvent(Ref* target, Handler action,
|
||||||
|
|
||||||
//remove all invocations if the target and action are null
|
//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?
|
//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)
|
if (!target && !action)
|
||||||
{
|
{
|
||||||
//remove objects
|
//remove objects
|
||||||
|
@ -215,7 +215,7 @@ void Control::removeTargetWithActionForControlEvent(Ref* target, Handler action,
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const auto &invocation : tobeRemovedInvocations) {
|
for(const auto &invocation : tobeRemovedInvocations) {
|
||||||
eventInvocationList.eraseObject(invocation, bDeleteObjects);
|
eventInvocationList.eraseObject(invocation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,6 +233,47 @@ void TemplateVectorTest::onEnter()
|
||||||
vec6.eraseObject(vec6.at(2));
|
vec6.eraseObject(vec6.at(2));
|
||||||
CCASSERT(vec6.at(2)->getTag() == 1013, "");
|
CCASSERT(vec6.at(2)->getTag() == 1013, "");
|
||||||
vec6.clear();
|
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
|
// Check the retain count in vec7
|
||||||
CCASSERT(vec7.size() == 20, "");
|
CCASSERT(vec7.size() == 20, "");
|
||||||
|
|
Loading…
Reference in New Issue