1 #include "DynParaLoop.hxx"
2 #include "LinkInfo.hxx"
6 #include "YacsTrace.hxx"
9 using namespace YACS::ENGINE;
11 const char DynParaLoop::NAME_OF_SPLITTED_SEQ_OUT[]="SmplPrt";
13 const char DynParaLoop::NAME_OF_NUMBER_OF_BRANCHES[]="nbBranches";
15 AnyOutputPort::AnyOutputPort(const std::string& name, Node *node, TypeCode *type):OutputPort(name,node,type),
16 DataPort(name,node,type),Port(node),_data(0)
20 AnyOutputPort::AnyOutputPort(const AnyOutputPort& other, Node *newHelder):OutputPort(other,newHelder),
21 DataPort(other,newHelder),
22 Port(other,newHelder),_data(0)
26 AnyOutputPort::~AnyOutputPort()
32 void AnyOutputPort::setValue(Any *data)
41 OutputPort *AnyOutputPort::clone(Node *newHelder) const
43 return new AnyOutputPort(*this,newHelder);
46 DynParaLoop::DynParaLoop(const std::string& name, TypeCode *typeOfDataSplitted):ComposedNode(name),_node(0),_initNode(0),_nbOfEltConsumed(0),
47 _nbOfBranches(NAME_OF_NUMBER_OF_BRANCHES,this,Runtime::_tc_int),
48 _splittedPort(NAME_OF_SPLITTED_SEQ_OUT,this,typeOfDataSplitted)
52 DynParaLoop::~DynParaLoop()
58 DynParaLoop::DynParaLoop(const DynParaLoop& other, ComposedNode *father, bool editionOnly):ComposedNode(other,father),
59 _nbOfBranches(other._nbOfBranches,this),
60 _splittedPort(other._splittedPort,this),
61 _node(0),_initNode(0),_nbOfEltConsumed(0)
64 _node=other._node->clone(this,editionOnly);
66 _initNode=other._initNode->clone(this,editionOnly);
67 const AnyOutputPort& startOfLinksToReproduce=other._splittedPort;
68 set<InPort *> endsOfLinksToReproduce=startOfLinksToReproduce.edSetInPort();
69 for(set<InPort *>::iterator iter=endsOfLinksToReproduce.begin();iter!=endsOfLinksToReproduce.end();iter++)
70 edAddLink(&_splittedPort,getInPort(other.getPortName(*iter)));
73 Node *DynParaLoop::edSetNode(Node *node)
81 std::string what = "DynParaLoop::edSetNode: node "; what += node->getName(); what += " is not orphan ! ";
82 throw Exception(what);
85 if(_initNode->getName()==node->getName())
87 std::string what = "DynParaLoop::edSetNode: node "; what += node->getName(); what += " has the same name than init node already in "; what+=_name; what+="! ";
88 throw Exception(what);
91 checkNoCrossHierachyWith(node);
92 ComposedNode::edRemoveChild(_node);
96 //set _modified flag so that edUpdateState can refresh state
101 void DynParaLoop::init(bool start)
103 ComposedNode::init(start);
106 string what("DynParaLoop::init : no node specified for ForEachLoop with name "); what +=_name;
107 throw Exception(what);
109 _nbOfBranches.exInit(start);
110 _splittedPort.exInit();
114 Node *DynParaLoop::edSetInitNode(Node *node)
122 std::string what = "DynParaLoop::edSetInitNode : node "; what += node->getName(); what += " is not orphan ! ";
123 throw Exception(what);
126 if(_node->getName()==node->getName())
128 std::string what = "DynParaLoop::edSetInitNode : node "; what += node->getName(); what += " has the same name than node already in "; what+=_name; what+="! ";
129 throw Exception(what);
132 checkNoCrossHierachyWith(node);
133 edRemoveChild(_initNode);
136 _initNode->_father=this;
141 int DynParaLoop::getNumberOfInputPorts() const
143 return ComposedNode::getNumberOfInputPorts()+1;
146 int DynParaLoop::getNumberOfOutputPorts() const
148 return ComposedNode::getNumberOfOutputPorts()+1;
151 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
153 list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
154 ret.push_back((OutputPort *)&_splittedPort);
158 OutPort *DynParaLoop::getOutPort(const std::string& name) const throw(Exception)
160 if(name==NAME_OF_SPLITTED_SEQ_OUT)
161 return (OutPort *)&_splittedPort;
162 return ComposedNode::getOutPort(name);
165 InputPort *DynParaLoop::getInputPort(const std::string& name) const throw(Exception)
167 if(name==NAME_OF_NUMBER_OF_BRANCHES)
168 return (InputPort *)&_nbOfBranches;
169 return ComposedNode::getInputPort(name);
172 OutputPort *DynParaLoop::getOutputPort(const std::string& name) const throw(Exception)
174 if(name==NAME_OF_SPLITTED_SEQ_OUT)
175 return (OutputPort *)&_splittedPort;
176 return ComposedNode::getOutputPort(name);
179 bool DynParaLoop::isPlacementPredictableB4Run() const
184 Node *DynParaLoop::edRemoveNode()
188 ComposedNode::edRemoveChild(_node);
194 Node *DynParaLoop::edRemoveInitNode()
198 ComposedNode::edRemoveChild(_initNode);
204 void DynParaLoop::edRemoveChild(Node *node) throw(Exception)
206 ComposedNode::edRemoveChild(node);
213 std::list<Node *> DynParaLoop::edGetDirectDescendants() const
217 ret.push_back(_node);
219 ret.push_back(_initNode);
223 std::list<InputPort *> DynParaLoop::getSetOfInputPort() const
225 list<InputPort *> ret=ComposedNode::getSetOfInputPort();
226 ret.push_back((InputPort *)&_nbOfBranches);
230 std::list<InputPort *> DynParaLoop::getLocalInputPorts() const
232 list<InputPort *> ret=ComposedNode::getLocalInputPorts();
233 ret.push_back((InputPort *)&_nbOfBranches);
237 unsigned DynParaLoop::getNumberOfBranchesCreatedDyn() const throw(Exception)
239 if(_execNodes.empty())
240 throw Exception("ForEachLoop::getNumberOfBranches : No branches created dynamically ! - ForEachLoop needs to run or to be runned to call getNumberOfBranches");
242 return _execNodes.size();
245 Node *DynParaLoop::getChildByShortName(const std::string& name) const throw(Exception)
248 if(name==_node->getName())
251 if(name==_initNode->getName())
253 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
254 throw Exception(what);
257 Node *DynParaLoop::getChildByNameExec(const std::string& name, unsigned id) const throw(Exception)
259 if(id>=getNumberOfBranchesCreatedDyn())
260 throw Exception("ForEachLoop::getChildByNameExec : invalid id - too large compared with dynamically created branches.");
262 if(name==_node->getName())
263 return _execNodes[id];
265 if(name==_initNode->getName())
266 return _execInitNodes[id];
267 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
268 throw Exception(what);
271 void DynParaLoop::cleanDynGraph()
273 for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
276 for(vector<Node *>::iterator iter2=_execInitNodes.begin();iter2!=_execInitNodes.end();iter2++)
282 * This method applies on newly cloned on exec nodes (_execNodes/_execInitNodes)
283 * the setting of input ports coming from outside of 'this'
285 void DynParaLoop::prepareInputsFromOutOfScope(int branchNb)
287 set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
288 portsToSetVals.erase(&_nbOfBranches);//_nbOfBranches inport is not a candidate of dynamically duplicated inport.
289 for(set< InPort * >::iterator iter=portsToSetVals.begin();iter!=portsToSetVals.end();iter++)
291 InputPort *curPortCasted=(InputPort *) *iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
292 void *val=curPortCasted->get();
293 InputPort *portToSet=getDynInputPortByAbsName(branchNb,getInPortName(*iter),true);
294 if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
296 portToSet->put((const void *)val);
297 portToSet->edNotifyReferencedBy(0);//This is to indicate that somewhere somebody deals with this inputport
298 //even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
303 void DynParaLoop::putValueOnBranch(Any *val, unsigned branchId, bool first)
305 bool isDispatched = false;
306 set<InPort *> inPrtLkdWthSplttdPrt=_splittedPort.edSetInPort();
307 for(set<InPort *>::iterator iter=inPrtLkdWthSplttdPrt.begin();iter!=inPrtLkdWthSplttdPrt.end();iter++)
309 std::string portNameOnCurPrt=getPortName(*iter);
310 InputPort *portOnGivenBranch=getDynInputPortByAbsName(branchId,portNameOnCurPrt,first);//Cast granted because impossible to have cross protocol with _splittedPort
311 //see OptimizerLoop::buildDelegateOf
312 if(portOnGivenBranch)
315 portOnGivenBranch->edNotifyReferencedBy(0);
316 InputPort *traducer=getRuntime()->adapt(portOnGivenBranch,
317 Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME,_splittedPort.edGetType());
318 traducer->put((const void *)val);
320 if(traducer!=portOnGivenBranch)
326 Any *tmp=val->clone();
327 _splittedPort.setValue(tmp);
332 DynParaLoop::TypeOfNode DynParaLoop::getIdentityOfNotifyerNode(const Node *node, unsigned& id)
335 for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++,id++)
339 for(vector<Node *>::iterator iter2=_execInitNodes.begin();iter2!=_execInitNodes.end();iter2++,id++)
344 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
346 if(_nbOfBranches.edIsManuallyInitialized())
347 if(_nbOfBranches.edGetNumberOfLinks()==0)
349 value=_nbOfBranches.getIntValue();
355 void DynParaLoop::forceMultiplicity(unsigned value)
357 _nbOfBranches.edRemoveAllLinksLinkedWithMe();
358 _nbOfBranches.edInit((int)value);
361 void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::list<ComposedNode *>& pointsOfView)
363 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
364 if(typeOfPortInstance!=InputPort::NAME)
365 throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop this is not possible");
368 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::list<ComposedNode *>& pointsOfView)
371 if(isInMyDescendance(port.first->getNode())==_initNode)
372 throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : a link starting from init node can't leave the scope of ForEachLoop node it belongs to.");
373 if(port.first==&_splittedPort)
374 throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : splitted port must be link within the scope of ForEachLoop node it belongs to.");
377 void DynParaLoop::checkCFLinks(const std::list<OutPort *>& starts, InputPort *end, unsigned char& alreadyFed, bool direction, LinkInfo& info) const
379 const char what[]="DynParaLoop::checkCFLinks : internal error.";
380 //First dealing checkCFLinks forwarding...
381 if(isInMyDescendance(end->getNode())==0)//no chance that _splittedPort is in starts due to buildDelegate.
382 solveObviousOrDelegateCFLinks(starts,end,alreadyFed,direction,info);
384 {//no forwarding here.
386 throw Exception(what);
387 //ASSERT(direction) : see DynParaLoop::checkControlDependancy only 'fw' filled.
388 if(*(starts.begin())!=&_splittedPort)
389 throw Exception(what);
390 if(alreadyFed==FREE_ST)
392 else if(alreadyFed==FED_ST)
393 {//Shame ! splittedPort fills a port already fed...
394 info.pushInfoLink(*(starts.begin()),end,I_USELESS);
400 * \param cross indicates if start -> end link is a DS link behind.
401 * \param fw out parameter.
402 * \param fwCross out parameter storing links where a cross has been detected.
403 * \param bw out parameter where backward links are stored.
405 void DynParaLoop::checkControlDependancy(OutPort *start, InPort *end, bool cross,
406 std::map < ComposedNode *, std::list < OutPort * >, SortHierarc >& fw,
407 std::vector<OutPort *>& fwCross,
408 std::map< ComposedNode *, std::list < OutPort *>, SortHierarc >& bw,
409 LinkInfo& info) const
411 if(start==&_splittedPort)
412 fw[(ComposedNode *)this].push_back(start);
414 throw Exception("DynParaLoop::checkControlDependancy : Internal error occured - should never been called !");
418 * \note : For a given name 'name' of port in absolute form from this, returns the corresponding InputPort instance of the
419 * port for the branch # 'branchNb'. The port can be part of _node or _initNode if it exists (if 'initNodeAdmitted' is true).
420 * \b WARNING : no check performed on 'branchNb' value to see if it is compatible with size of '_execNodes'.
421 * This method is called to dispatch value on each InputPort linked to this->._splitterNode._splittedPort
423 InputPort *DynParaLoop::getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted)
425 string portName, nodeName;
426 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true);
427 Node *staticChild = getChildByName(nodeName);
428 Node *desc=isInMyDescendance(staticChild);
431 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
432 return _execNodes[branchNb]->getInputPort(portName);
434 else if(desc==_initNode)
437 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
438 return _execInitNodes[branchNb]->getInputPort(portName);