App: Remove old DAG implementation.

This commit is contained in:
Joao Matos
2025-02-26 20:09:40 +00:00
committed by Chris Hennes
parent 46b9ff9c50
commit 006feaf276
7 changed files with 17 additions and 312 deletions

View File

@@ -78,13 +78,6 @@ recompute path. Also, it enables more complicated dependencies beyond trees.
#include <boost/bimap.hpp>
#include <boost/graph/strong_components.hpp>
#ifdef USE_OLD_DAG
#include <boost/graph/topological_sort.hpp>
#include <boost/graph/depth_first_search.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/visitors.hpp>
#endif // USE_OLD_DAG
#include <boost/regex.hpp>
#include <random>
#include <unordered_map>
@@ -2934,15 +2927,7 @@ std::vector<App::Document*> Document::getDependentDocuments(std::vector<App::Doc
void Document::_rebuildDependencyList(const std::vector<App::DocumentObject*>& objs)
{
#ifdef USE_OLD_DAG
_buildDependencyList(objs.empty() ? d->objectArray : objs,
false,
0,
&d->DepList,
&d->VertexObjectList);
#else
(void)objs;
#endif
}
/**
@@ -2973,156 +2958,6 @@ void Document::renameObjectIdentifiers(
}
}
#ifdef USE_OLD_DAG
int Document::recompute(const std::vector<App::DocumentObject*>& objs, bool force)
{
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
if (!force && testStatus(Document::SkipRecompute)) {
return 0;
}
Base::ObjectStatusLocker<Document::Status, Document> exe(Document::Recomputing, this);
// delete recompute log
d->clearRecomputeLog();
// updates the dependency graph
_rebuildDependencyList(objs);
std::list<Vertex> make_order;
DependencyList::out_edge_iterator j, jend;
try {
// this sort gives the execute
boost::topological_sort(d->DepList, std::front_inserter(make_order));
}
catch (const std::exception& e) {
std::cerr << "Document::recompute: " << e.what() << std::endl;
return -1;
}
// caching vertex to DocObject
for (std::map<DocumentObject*, Vertex>::const_iterator It1 = d->VertexObjectList.begin();
It1 != d->VertexObjectList.end();
++It1) {
d->vertexMap[It1->second] = It1->first;
}
#ifdef FC_LOGFEATUREUPDATE
std::clog << "make ordering: " << std::endl;
#endif
std::set<DocumentObject*> recomputeList;
for (std::list<Vertex>::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) {
DocumentObject* Cur = d->vertexMap[*i];
// Because of PropertyXLink, we should account for external objects
// TODO: make sure it is safe to rely on getNameInDocument() to check if
// object is in the document. If it crashes, then we should fix the code
// to properly nullify getNameInDocument(), rather than revert back to
// the inefficient isIn()
// if (!Cur || !isIn(Cur)) continue;
if (!Cur || !Cur->getNameInDocument()) {
continue;
}
#ifdef FC_LOGFEATUREUPDATE
std::clog << Cur->getNameInDocument() << " dep on:";
#endif
bool NeedUpdate = false;
// ask the object if it should be recomputed
if (Cur->mustExecute() == 1 || Cur->ExpressionEngine.depsAreTouched()) {
#ifdef FC_LOGFEATUREUPDATE
std::clog << "[touched]";
#endif
NeedUpdate = true;
}
else { // if (Cur->mustExecute() == -1)
// update if one of the dependencies is touched
for (boost::tie(j, jend) = out_edges(*i, d->DepList); j != jend; ++j) {
DocumentObject* Test = d->vertexMap[target(*j, d->DepList)];
if (!Test) {
continue;
}
#ifdef FC_LOGFEATUREUPDATE
std::clog << " " << Test->getNameInDocument();
#endif
if (Test->isTouched()) {
NeedUpdate = true;
#ifdef FC_LOGFEATUREUPDATE
std::clog << "[touched]";
#endif
}
}
}
// if one touched recompute
if (NeedUpdate) {
Cur->touch();
#ifdef FC_LOGFEATUREUPDATE
std::clog << " => Recompute feature";
#endif
recomputeList.insert(Cur);
}
#ifdef FC_LOGFEATUREUPDATE
std::clog << std::endl;
#endif
}
#ifdef FC_LOGFEATUREUPDATE
std::clog << "Have to recompute the following document objects" << std::endl;
for (std::set<DocumentObject*>::const_iterator it = recomputeList.begin();
it != recomputeList.end();
++it) {
std::clog << " " << (*it)->getNameInDocument() << std::endl;
}
#endif
for (std::list<Vertex>::reverse_iterator i = make_order.rbegin(); i != make_order.rend(); ++i) {
DocumentObject* Cur = d->vertexMap[*i];
if (!Cur || !isIn(Cur)) {
continue;
}
if (recomputeList.find(Cur) != recomputeList.end()
|| Cur->ExpressionEngine.depsAreTouched()) {
if (_recomputeFeature(Cur)) {
// if something happened break execution of recompute
d->vertexMap.clear();
return -1;
}
signalRecomputedObject(*Cur);
++objectCount;
}
}
// reset all touched
for (std::map<Vertex, DocumentObject*>::iterator it = d->vertexMap.begin();
it != d->vertexMap.end();
++it) {
// TODO: check the TODO comments above for details
// if ((it->second) && isIn(it->second))
if ((it->second) && it->second->getNameInDocument()) {
it->second->purgeTouched();
}
}
d->vertexMap.clear();
signalRecomputed(*this);
return objectCount;
}
#else // ifdef USE_OLD_DAG
int Document::recompute(const std::vector<App::DocumentObject*>& objs,
bool force,
bool* hasError,
@@ -3315,8 +3150,6 @@ int Document::recompute(const std::vector<App::DocumentObject*>& objs,
return objectCount;
}
#endif // USE_OLD_DAG
/*!
Does almost the same as topologicalSort() until no object with an input degree of zero
can be found. It then searches for objects with an output degree of zero until neither
@@ -3912,20 +3745,6 @@ void Document::removeObject(const char* sName)
signalTransactionRemove(*pos->second, 0);
}
#ifdef USE_OLD_DAG
if (!d->vertexMap.empty()) {
// recompute of document is running
for (std::map<Vertex, DocumentObject*>::iterator it = d->vertexMap.begin();
it != d->vertexMap.end();
++it) {
if (it->second == pos->second) {
it->second = 0; // just nullify the pointer
break;
}
}
}
#endif // USE_OLD_DAG
// Before deleting we must nullify all dependent objects
breakDependency(pos->second, true);