Browse Source

Recursive evaluating

test
Michael Uleysky 9 years ago
parent
commit
9dbc3abaed
  1. 196
      src/deptree.cpp
  2. 10
      src/deptree.h
  3. 6
      src/main.cpp

196
src/deptree.cpp

@ -1,3 +1,4 @@
#include <stack>
#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<NodeVector::const_iterator> 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<DepTree*>(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 ("<<G_tosave[leaf->index]->Dump()<<")"<<std::endl;
}
if(DepTree::PRINT==leaf->type)
{
COUT(INFO)<<"print ("<<G_toprint[leaf->index]->Dump()<<")"<<std::endl;
}
if(DepTree::VAR==leaf->type)
{
err=false;
ob=G_vars.at(leaf->name);
// Main working call
eob=ob->Evaluate(&err);
if(err)
{
COUT(ERROR)<<" in definition of variable "<<leaf->name<<std::endl;
// Begin locked section (errflag set)
mtx[0].lock();
*errflag=1;
mtx[0].unlock();
// End locked section
return;
}
// eob is evaluated object
if(0!=eob) delete ob;
else eob=ob;
G_vars.erase(leaf->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 ("<<G_tosave[leaf->index]->Dump()<<")"<<std::endl;
}
if(DepTree::PRINT==leaf->type)
{
COUT(INFO)<<"print ("<<G_toprint[leaf->index]->Dump()<<")"<<std::endl;
}
if(DepTree::VAR==leaf->type)
{
err=false;
ob=G_vars.at(leaf->name);
// Main working call
eob=ob->Evaluate(&err);
if(err)
{
COUT(ERROR)<<" in definition of variable "<<leaf->name<<std::endl;
*errflag=1;
return;
}
// eob is evaluated object
if(0!=eob) delete ob;
else eob=ob;
G_vars.erase(leaf->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;
}

10
src/deptree.h

@ -3,10 +3,13 @@
#include <set>
#include <vector>
#include <string>
#include <mutex>
#include <thread>
#include "globals.h"
class DepTree
{
typedef std::vector<DepTree*> LeafVector;
enum NodeType {NOTDEF,ROOT,SAVE,PRINT,VAR};
typedef std::set<DepTree*> 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

6
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"<<std::endl;
DumpConfig();
COUT(INFO)<<sizeof(DepTree)<<" "<<sizeof(ObjectList)<<std::endl;
COUT(INFO)<<"Evaluate tree ";
ret=DPTree->EvaluateTree(); if(ret!=0) { ClearGlobals(); delete DPTree; return 1;}
COUT(INFO)<<"Ok"<<std::endl;
ClearGlobals();
delete DPTree;

Loading…
Cancel
Save