add EntityTree::_pendingDelete for delayed deletes

for case where EntitySimuation needs time to remove pointers
This commit is contained in:
Andrew Meadows 2015-05-01 10:43:58 -07:00
parent 4cb469dd79
commit 31ca5b9eef
2 changed files with 26 additions and 8 deletions

View file

@ -350,10 +350,12 @@ void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator)
} }
if (_simulation && theEntity->getSimulation()) { if (_simulation && theEntity->getSimulation()) {
// delegate entity destruction to the simulation so it can clean up its own pointers _simulation->removeEntity(theEntity);
_simulation->deleteEntity(theEntity); // we need to give the simulation time to cleanup its own pointers
// so we push theEntity onto the _pendingDeletes and check again later.
_pendingDeletes.insert(theEntity);
} else { } else {
delete theEntity; // we can delete the entity directly now delete theEntity; // we can delete the entity immediately
} }
} }
if (_simulation) { if (_simulation) {
@ -754,16 +756,30 @@ void EntityTree::update() {
lockForWrite(); lockForWrite();
_simulation->lock(); _simulation->lock();
_simulation->updateEntities(); _simulation->updateEntities();
SetOfEntities entitiesToDelete; _simulation->getEntitiesToDelete(_pendingDeletes);
_simulation->getEntitiesToDelete(entitiesToDelete);
_simulation->unlock(); _simulation->unlock();
if (entitiesToDelete.size() > 0) { if (_pendingDeletes.size() > 0) {
// translate into list of ID's // translate into list of ID's
QSet<EntityItemID> idsToDelete; QSet<EntityItemID> idsToDelete;
foreach (EntityItem* entity, entitiesToDelete) { SetOfEntities::iterator entityItr = _pendingDeletes.begin();
idsToDelete.insert(entity->getEntityItemID()); while (entityItr != _pendingDeletes.end()) {
EntityItem* entity = *entityItr;
if (entity->getElement()) {
// this entity is still in an element so we push it's ID on a list (and delete the roundabout way)
idsToDelete.insert(entity->getEntityItemID());
entityItr = _pendingDeletes.erase(entityItr);
} else if (!entity->getSimulation()) {
// the entity is not in any simulation so we can delete immediately
delete entity;
entityItr = _pendingDeletes.erase(entityItr);
} else {
// we're waiting for the simulation to cleanup its own data structure
// so we leave it on the _pendingDeletes and will try again later
++entityItr;
}
} }
// delete these things the roundabout way
deleteEntities(idsToDelete, true); deleteEntities(idsToDelete, true);
} }
unlock(); unlock();

View file

@ -18,6 +18,7 @@
#include "EntityTreeElement.h" #include "EntityTreeElement.h"
#include "DeleteEntityOperator.h" #include "DeleteEntityOperator.h"
typedef QSet<EntityItem*> SetOfEntities;
class Model; class Model;
class EntitySimulation; class EntitySimulation;
@ -197,6 +198,7 @@ private:
QHash<EntityItemID, EntityItemID> _changedEntityIDs; QHash<EntityItemID, EntityItemID> _changedEntityIDs;
EntitySimulation* _simulation; EntitySimulation* _simulation;
SetOfEntities _pendingDeletes;
bool _wantEditLogging = false; bool _wantEditLogging = false;
}; };