Salome HOME
3759fc0947804cfd574397f876fd8178cd6a15ed
[modules/yacs.git] / src / engine / Bloc.hxx
1 // Copyright (C) 2006-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #ifndef __BLOC_HXX__
21 #define __BLOC_HXX__
22
23 #include "YACSlibEngineExport.hxx"
24 #include "StaticDefinedComposedNode.hxx"
25 #include "AutoRefCnt.hxx"
26
27 namespace YACS
28 {
29   namespace ENGINE
30   {
31     class PartDefinition;
32     class DynParaLoop;
33     class AbstractPoint;
34     class PlayGround;
35     class YACSLIBENGINE_EXPORT Bloc : public StaticDefinedComposedNode
36     {
37     protected:
38       std::list<Node *> _setOfNode;//OWNERSHIP OF ALL NODES
39       //! For internal calculations
40       mutable std::map<Node *,std::set<Node *> > *_fwLinks;
41       //! For internal calculations
42       mutable std::map<Node *,std::set<Node *> > *_bwLinks;
43     protected:
44       Node *simpleClone(ComposedNode *father, bool editionOnly=true) const;
45     public:
46       Bloc(const Bloc& other, ComposedNode *father, bool editionOnly);
47       Bloc(const std::string& name);
48       virtual ~Bloc();
49       bool isFinished();
50       int getNumberOfCFLinks() const;
51       void init(bool start=true);
52       void getReadyTasks(std::vector<Task *>& tasks);
53       void exUpdateState();
54       //Node* DISOWNnode is a SWIG notation to indicate that the ownership of the node is transfered to C++
55       bool edAddChild(Node *DISOWNnode) throw(Exception);
56       void edRemoveChild(Node *node) throw(Exception);
57       std::list<Node *> getChildren() const { return _setOfNode; }
58       std::list<Node *> edGetDirectDescendants() const { return _setOfNode; }
59       std::vector< std::list<Node *> > splitIntoIndependantGraph() const;
60       Node *getChildByShortName(const std::string& name) const throw(Exception);
61       virtual void writeDot(std::ostream &os) const;
62       void accept(Visitor *visitor);
63       template<bool direction>
64       void findAllPathsStartingFrom(Node *start, std::list< std::vector<Node *> >& vec, std::map<Node *, std::set<Node *> >& accelStr) const;
65       template<bool direction>
66       void findAllNodesStartingFrom(Node *start, std::set<Node *>& result, std::map<Node *, std::set<Node *> >& accelStr, LinkInfo& info) const;
67       virtual std::string typeName() { return "YACS__ENGINE__Bloc"; }
68       int getMaxLevelOfParallelism() const;
69       double getWeightRegardingDPL() const;
70       void removeRecursivelyRedundantCL();
71       void partitionRegardingDPL(const PartDefinition *pd, std::map<ComposedNode *, YACS::BASES::AutoRefCnt<PartDefinition> >& zeMap);
72       void fitToPlayGround(const PlayGround *pg);
73     protected:
74       bool areAllSubNodesFinished() const;
75       bool areAllSubNodesDone() const;
76       bool isNameAlreadyUsed(const std::string& name) const;
77       void checkNoCyclePassingThrough(Node *node) throw(Exception);
78       std::vector< std::pair<OutGate *, InGate *> > getSetOfInternalCFLinks() const;
79       YACS::Event updateStateOnFinishedEventFrom(Node *node);
80       YACS::Event updateStateOnFailedEventFrom(Node *node, const Executor *execInst);
81       void initComputation() const;
82       void performCFComputationsOnlyOneLevel(LinkInfo& info) const;
83       void performCFComputations(LinkInfo& info) const;
84       void destructCFComputations(LinkInfo& info) const;
85       void checkControlDependancy(OutPort *start, InPort *end, bool cross,
86                                   std::map < ComposedNode *,  std::list < OutPort * >, SortHierarc >& fw,
87                                   std::vector<OutPort *>& fwCross,
88                                   std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
89                                   LinkInfo& info) const;
90       bool areLinked(Node *start, Node *end, bool fw) const;
91       bool arePossiblyRunnableAtSameTime(Node *start, Node *end) const;
92       void checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const;
93       static void verdictForOkAndUseless1(const std::map<Node *,std::list <OutPort *> >& pool, InputPort *end, const std::vector<Node *>& candidates,
94                                           unsigned char& alreadyFed, bool direction, LinkInfo& info);
95       static void verdictForCollapses(const std::map<Node *,std::list <OutPort *> >& pool, InputPort *end, const std::set<Node *>& candidates,
96                                       unsigned char& alreadyFed, bool direction, LinkInfo& info);
97       void seekOkAndUseless1(std::vector<Node *>& okAndUseless1, std::set<Node *>& allNodes) const;
98       void seekUseless2(std::vector<Node *>& useless2, std::set<Node *>& allNodes) const;
99     private:
100       std::list< AbstractPoint * > analyzeParallelism() const;
101       static void findUselessLinksIn(const std::list< std::vector<Node *> >& res , LinkInfo& info);
102       template<bool direction>
103       static unsigned appendIfAlreadyFound(std::list< std::vector<Node *> >& res, const std::vector<Node *>& startRes, Node *node, std::map<Node *, std::set<Node *> >& fastFinder);
104       static void updateWithNewFind(const std::vector<Node *>& path, std::map<Node *, std::set<Node *> >& fastFinder);
105     };
106
107     template<bool direction>
108     struct CFDirectionVisTraits
109     {   
110     };
111     
112     template<>
113     struct CFDirectionVisTraits<true>
114     {
115       typedef std::list< std::pair<InGate *,bool> >::iterator Iterator;
116       typedef std::list< std::pair<InGate *,bool> >& Nexts;
117       static Nexts getNexts(Node *node) { return node->getOutGate()->edMapInGate(); }
118     };
119
120     
121     template<>
122     struct CFDirectionVisTraits<false>
123     {
124       typedef std::list< std::pair<OutGate *,bool> >::iterator Iterator;
125       typedef std::list< std::pair<OutGate *,bool> >& Nexts;
126       static Nexts getNexts(Node *node) { return node->getInGate()->edMapOutGate(); }
127     };
128
129     /*!
130      * Internal method for CF computation. Given 'fastFinder' it searched 'node' to see if an already found path in 'res' go through 'node'.
131      * If true all paths are deduced and append to res and 'fastFinder' is updated for next turn.
132      */
133     template<bool direction>
134     unsigned Bloc::appendIfAlreadyFound(std::list< std::vector<Node *> >& res, const std::vector<Node *>& startRes, Node *node, std::map<Node *, std::set<Node *> >& fastFinder)
135     {
136       std::map<Node *, std::set<Node *> >::iterator iter=fastFinder.find(node);
137       if(iter==fastFinder.end())
138         return 0;
139       unsigned ret=0;
140       std::vector<std::pair<std::set<Node *>::iterator, std::set<Node *>::iterator > > li;
141       std::pair<std::set<Node *>::iterator, std::set<Node *>::iterator> ipr(((*iter).second).begin(),((*iter).second).end());
142       li.push_back(ipr);
143       std::vector<Node *> work(startRes);
144       std::list< std::vector<Node *> >::iterator where=res.end(); where--;
145       std::list< std::vector<Node *> >::iterator updates=where;
146       while(!li.empty())
147         {
148           if(li.back().first!=li.back().second)
149             {
150               work.push_back(*(li.back().first));
151               if(CFDirectionVisTraits<direction>::getNexts(work.back()).empty())
152                 {
153                   where=res.insert(where,work);
154                   ret++;
155                   li.back().first++;
156                   work.pop_back();
157                 }
158               else
159                 {
160                   std::set<Node *>& s=fastFinder[*(li.back().first)];
161                   std::pair<std::set<Node *>::iterator, std::set<Node *>::iterator> pr(s.begin(),s.end());
162                   li.push_back(pr);
163                 }
164             }
165           else
166             {
167               work.pop_back();
168               li.pop_back();
169               if(!li.empty())
170                 li.back().first++;
171             }
172         }
173       updates--;
174       for(unsigned i=0;i<ret;i++,updates--)
175         updateWithNewFind(*updates,fastFinder);
176       return ret;
177     }
178
179     template<bool direction>
180     void Bloc::findAllNodesStartingFrom(Node *start, std::set<Node *>& result, 
181                                         std::map<Node *, std::set<Node *> >& accelStr, LinkInfo& info) const
182     {
183       std::list< std::vector<Node *> > li;
184       findAllPathsStartingFrom<direction>(start,li,accelStr);
185       for(std::list< std::vector<Node *> >::const_iterator iter=li.begin();iter!=li.end();iter++)
186         for(std::vector<Node *>::const_iterator iter2=(*iter).begin()+1;iter2!=(*iter).end();iter2++)
187           result.insert(*iter2);
188       if(direction)
189         findUselessLinksIn(li,info);
190     }
191
192     /*!
193      * Method for CF computation.DFS visitor is used.
194      * if direction is true forward visiting is performed, if false backward is performed.
195      * \param start \b must be a direct descendant of 'this'.
196      * \param vec :
197      * \param accelStr
198      */
199     template<bool direction>
200     void Bloc::findAllPathsStartingFrom(Node *start, std::list< std::vector<Node *> >& vec, 
201                                         std::map<Node *, std::set<Node *> >& accelStr) const
202     {
203       initComputation();
204       Node *current=start;
205       int caseId=0;
206       int idInCase=0;
207       vec.push_back(std::vector<Node *>());
208       typename CFDirectionVisTraits<direction>::Iterator iter;
209       std::list< std::vector<Node *> >::iterator curLine=vec.begin();
210       while(start->_colour!=YACS::Black)
211         {
212           (*curLine).push_back(current);
213           idInCase++;
214           //
215           if(CFDirectionVisTraits<direction>::getNexts(current).empty())
216             {
217               
218               vec.push_back(std::vector<Node *>((*curLine)));
219               updateWithNewFind(*curLine,accelStr);
220               current->_colour=YACS::Black;
221               curLine++;
222               if(idInCase>1)
223                 {
224                   idInCase-=2;
225                   current=(*curLine)[idInCase];
226                   (*curLine).pop_back();
227                   (*curLine).pop_back();
228                 }
229               continue;
230             }
231           if(current->_colour==YACS::Black)
232             {
233               appendIfAlreadyFound<direction>(vec,(*curLine),current,accelStr);
234               curLine=vec.end(); curLine--;
235               current->_colour=YACS::Black;
236               if(idInCase>1)
237                 {
238                   idInCase-=2;
239                   current=(*curLine)[idInCase];
240                   (*curLine).pop_back();
241                   (*curLine).pop_back();
242                 }
243               continue;
244             }
245           for(iter=CFDirectionVisTraits<direction>::getNexts(current).begin();iter!=CFDirectionVisTraits<direction>::getNexts(current).end();iter++)
246             if(!(*iter).second)
247               break;
248           if(iter==CFDirectionVisTraits<direction>::getNexts(current).end())
249             {//Fail this branch should be forgotten go rev
250               current->_colour=YACS::Black;
251               (*curLine).pop_back();
252               if(idInCase>1)
253                 {
254                   idInCase-=2;
255                   current=(*curLine)[idInCase];
256                   (*curLine).pop_back();
257                 }
258             }
259           else
260             {
261               //Nothing to signal continuing in this direction hoping to find
262               current=(*iter).first->getNode();
263               (*iter).second=true;
264             }
265         }
266       vec.pop_back();
267     }
268   }
269 }
270
271
272 #endif