diff --git a/src/deptree.cpp b/src/deptree.cpp index 5f80f58..1f8597b 100644 --- a/src/deptree.cpp +++ b/src/deptree.cpp @@ -1,3 +1,4 @@ +#include #include "deptree.h" int DepTree::CreateNodeFromVar(const std::string& var, UsedType& used, CallStack& callstack) @@ -142,3 +143,198 @@ DepTree* DepTree::FindNodeByVar(const std::string& var) const while(curnode->parents.size()!=0) curnode=*(curnode->parents.begin()); return curnode->FindNodeByVarFromCurrent(var); } + + +DepTree::LeafVector DepTree::FindLeafNodes() const +{ + LeafVector leafs; + std::stack path,ends; + NodeVector::const_iterator it,end; + // define isvisited as reversion of last visited + bool isvisited=!visited; + // ascending to root + const DepTree* root=this; + while(root->parents.size()!=0) root=*(root->parents.begin()); + + const DepTree* curnode=root; + curnode->visited=isvisited; + it=curnode->childrens.begin(); + end=curnode->childrens.end(); + + while(true) + { + if(it!=end) + { + if((*it)->visited==isvisited) {it++; continue;} + path.push(it); ends.push(end); + curnode=(*it); + curnode->visited=isvisited; + it=curnode->childrens.begin(); + end=curnode->childrens.end(); + if(it==end) leafs.push_back(const_cast(curnode)); + } + else + { + if(path.size()==0) break; + it=path.top(); path.pop(); + end=ends.top(); ends.pop(); + it++; + } + } + + return leafs; +} + + +// Multi-threaded version +void TreeEvaluate(std::mutex* mtx, int* errflag, DepTree::LeafVector* leafs, const DepTree* root) +{ + // mtx[0] - mutex for manipulating with LeafVector + // mtx[1] - mutex for manipulating with tree + DepTree* leaf; + ObjectBase *ob,*eob; + bool err; + while(true) + { + // Begin locked section (errflag check, leafs manipulations) + mtx[0].lock(); + // Is was error? + if(0!=errflag) {mtx[0].unlock(); return;} + // Is work finished? + if(0==root->childrens.size()) {mtx[0].unlock(); return;} + // Is jobs awaiting? + if(0==leafs->size()) {mtx[0].unlock(); std::this_thread::yield(); std::this_thread::sleep_for(std::chrono::milliseconds(100)); continue;} + // Select working node + leaf=*(leafs->begin()); + // and remove its from list + leafs->erase(leafs->begin()); + mtx[0].unlock(); + // End locked section + + if(DepTree::SAVE==leaf->type) + { + COUT(INFO)<<"save ("<index]->Dump()<<")"<type) + { + COUT(INFO)<<"print ("<index]->Dump()<<")"<type) + { + err=false; + ob=G_vars.at(leaf->name); + // Main working call + eob=ob->Evaluate(&err); + if(err) + { + COUT(ERROR)<<" in definition of variable "<name<name); // Concurrent access is safe + // Begin locked section + mtx[1].lock(); + for(auto& i:leaf->parents) + { + // leaf not children of anyone + i->childrens.erase(leaf); + // Replace variable on eob + if(DepTree::SAVE==i->type) G_tosave[i->index]->ReplaceVar(leaf->name,eob); // ReplaceVar always return 0 for ObjectList + if(DepTree::PRINT==i->type) G_toprint[i->index]->ReplaceVar(leaf->name,eob); + if(DepTree::VAR==i->type) + { + ob=G_vars[i->name]->ReplaceVar(leaf->name,eob); + if(0!=ob) {delete G_vars[i->name]; G_vars[i->name]=ob;} + } + // If node have no children, it's a new leaf node + if(0==i->childrens.size() && DepTree::ROOT!=i->type) leafs->push_back(i); + } + mtx[1].unlock(); + // End locked section + leaf->parents.clear(); + delete leaf; + } + } +} + + +// Single-threaded version +void TreeEvaluate(int* errflag, DepTree::LeafVector* leafs) +{ + DepTree* leaf; + ObjectBase *ob,*eob; + bool err; + while(0!=leafs->size()) + { + // Select working node + leaf=*(leafs->begin()); + // and remove its from list + leafs->erase(leafs->begin()); + + if(DepTree::SAVE==leaf->type) + { + COUT(INFO)<<"save ("<index]->Dump()<<")"<type) + { + COUT(INFO)<<"print ("<index]->Dump()<<")"<type) + { + err=false; + ob=G_vars.at(leaf->name); + // Main working call + eob=ob->Evaluate(&err); + if(err) + { + COUT(ERROR)<<" in definition of variable "<name<name); // Concurrent access is safe + for(auto& i:leaf->parents) + { + // leaf not children of anyone + i->childrens.erase(leaf); + // Replace variable on eob + if(DepTree::SAVE==i->type) G_tosave[i->index]->ReplaceVar(leaf->name,eob); // ReplaceVar always return 0 for ObjectList + if(DepTree::PRINT==i->type) G_toprint[i->index]->ReplaceVar(leaf->name,eob); + if(DepTree::VAR==i->type) + { + ob=G_vars[i->name]->ReplaceVar(leaf->name,eob); + if(0!=ob) {delete G_vars[i->name]; G_vars[i->name]=ob;} + } + // If node have no children, it's a new leaf node + if(0==i->childrens.size() && DepTree::ROOT!=i->type) leafs->push_back(i); + } + leaf->parents.clear(); + delete leaf; + } + } +} + + +int DepTree::EvaluateTree() +{ + int errflag=0; + LeafVector leafs=FindLeafNodes(); + + TreeEvaluate(&errflag,&leafs); + return errflag; +} diff --git a/src/deptree.h b/src/deptree.h index 274b73b..a74e529 100644 --- a/src/deptree.h +++ b/src/deptree.h @@ -3,10 +3,13 @@ #include #include #include +#include +#include #include "globals.h" class DepTree { + typedef std::vector LeafVector; enum NodeType {NOTDEF,ROOT,SAVE,PRINT,VAR}; typedef std::set NodeVector; @@ -16,13 +19,15 @@ class DepTree NodeType type; G_toType::size_type index; std::string name; + mutable bool visited; int CreateNodeFromVar(const std::string& var, UsedType& used, CallStack& callstack); int CreateNodeFromSP(NodeType list, G_toType::size_type ind, UsedType& used); DepTree* FindNodeByVarFromCurrent(const std::string& var) const; DepTree* FindNodeByVar(const std::string& var) const; + LeafVector FindLeafNodes() const; public: - DepTree():type(DepTree::NOTDEF) {} + DepTree():type(DepTree::NOTDEF),visited(false) {} DepTree(const DepTree&) = delete; ~DepTree() { @@ -35,6 +40,9 @@ public: } int CreateGlobalTree(UsedType& used); + int EvaluateTree(); + friend void TreeEvaluate(std::mutex* mtx, int* errflag, LeafVector* leafs, const DepTree* root); + friend void TreeEvaluate(int* errflag, LeafVector* leafs); }; #endif diff --git a/src/main.cpp b/src/main.cpp index d7f0c60..1c28619 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,9 +41,9 @@ int main(int argc, char** argv) ret=CheckFunctions(); if(ret!=0) { ClearGlobals(); delete DPTree; return 1;} COUT(INFO)<<"Ok"<EvaluateTree(); if(ret!=0) { ClearGlobals(); delete DPTree; return 1;} + COUT(INFO)<<"Ok"<