diff --git a/src/App/Document.cpp b/src/App/Document.cpp index ce9fc6dc6561..d4fd8e0b99d6 100644 --- a/src/App/Document.cpp +++ b/src/App/Document.cpp @@ -2491,15 +2491,13 @@ int Document::recompute(const std::vector &objs) #else //ifdef USE_OLD_DAG -int Document::recompute(const std::vector &objs) -{ +int Document::recompute(const std::vector &objs) { + int objectCount = 0; + if (testStatus(Document::Recomputing)) { // this is clearly a bug in the calling instance throw Base::RuntimeError("Nested recomputes of a document are not allowed"); } - - int objectCount = 0; - // The 'SkipRecompute' flag can be (tmp.) set to avoid too many // time expensive recomputes bool skip = testStatus(Document::SkipRecompute); @@ -2534,7 +2532,7 @@ int Document::recompute(const std::vector &objs) cerr << "App::Document::recompute(): cyclic dependency detected" << endl; topoSortedObjects = d->partialTopologicalSort(depObjs); } - for (auto objIt = topoSortedObjects.rbegin(); objIt != topoSortedObjects.rend(); ++objIt){ + std::reverse(topoSortedObjects.begin(),topoSortedObjects.end()); #else vector topoSortedObjects; try { @@ -2544,28 +2542,44 @@ int Document::recompute(const std::vector &objs) topoSortedObjects = d->partialTopologicalSort(getDependencyList(objs.empty()?d->objectArray:objs,false)); std::reverse(topoSortedObjects.begin(),topoSortedObjects.end()); } - for (auto objIt = topoSortedObjects.begin(); objIt != topoSortedObjects.end(); ++objIt){ #endif - // ask the object if it should be recomputed - if ((*objIt)->isTouched() || (*objIt)->mustExecute() == 1){ - objectCount++; - if (_recomputeFeature(*objIt)) { - // if something happened break execution of recompute - return -1; - } - else{ - (*objIt)->purgeTouched(); - // set all dependent object touched to force recompute - for (auto inObjIt : (*objIt)->getInList()) - inObjIt->touch(); + size_t idx = 0; + // maximum two passes to allow some form of dependency inversion + for(int passes=0; passes<2 && idxisTouched() || obj->mustExecute() == 1) { + objectCount++; + if (_recomputeFeature(obj)) { + // if something happened break execution of recompute + return -1; + } + else{ + obj->purgeTouched(); + // set all dependent object touched to force recompute + for (auto inObjIt : obj->getInList()) + inObjIt->touch(); + } } } - } - if(FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) { // check if all objects are recalculated which were thouched - for (auto obj : topoSortedObjects) { - if (obj->isTouched()) - FC_ERR(obj->getNameInDocument() << " still touched after recompute"); + for (size_t i=0;isetStatus(ObjectStatus::Recompute2,false); + if(obj->isTouched()) { + if(passes>0) + FC_ERR(obj->getNameInDocument() << " still touched after recompute"); + else{ + FC_LOG(obj->getNameInDocument() << " still touched after recompute"); + if(idx>=topoSortedObjects.size()) { + // let's start the next pass on the first touched object + idx = i; + } + obj->setStatus(ObjectStatus::Recompute2,true); + } + } } } diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index e74b17e82264..f8d497522b41 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -52,7 +52,8 @@ enum ObjectStatus { Remove = 5, PythonCall = 6, Destroy = 7, - Expand = 16 + Recompute2 = 8, + Expand = 16, }; /** Return object for feature execution