1 #include "DynParaLoop.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 ComposedNode::edRemoveChild(_node);
98 void DynParaLoop::init(bool start)
100 ComposedNode::init(start);
103 string what("DynParaLoop::init : no node specified for ForEachLoop with name "); what +=_name;
104 throw Exception(what);
106 _nbOfBranches.exInit(start);
107 _splittedPort.exInit();
111 Node *DynParaLoop::edSetInitNode(Node *node)
119 std::string what = "DynParaLoop::edSetInitNode : node "; what += node->getName(); what += " is not orphan ! ";
120 throw Exception(what);
123 if(_node->getName()==node->getName())
125 std::string what = "DynParaLoop::edSetInitNode : node "; what += node->getName(); what += " has the same name than node already in "; what+=_name; what+="! ";
126 throw Exception(what);
129 edRemoveChild(_initNode);
132 _initNode->_father=this;
136 int DynParaLoop::getNumberOfInputPorts() const
138 return ComposedNode::getNumberOfInputPorts()+1;
141 int DynParaLoop::getNumberOfOutputPorts() const
143 return ComposedNode::getNumberOfOutputPorts()+1;
146 std::list<OutputPort *> DynParaLoop::getSetOfOutputPort() const
148 list<OutputPort *> ret=ComposedNode::getSetOfOutputPort();
149 ret.push_back((OutputPort *)&_splittedPort);
153 OutPort *DynParaLoop::getOutPort(const std::string& name) const throw(Exception)
155 if(name==NAME_OF_SPLITTED_SEQ_OUT)
156 return (OutPort *)&_splittedPort;
157 return ComposedNode::getOutPort(name);
160 InputPort *DynParaLoop::getInputPort(const std::string& name) const throw(Exception)
162 if(name==NAME_OF_NUMBER_OF_BRANCHES)
163 return (InputPort *)&_nbOfBranches;
164 return ComposedNode::getInputPort(name);
167 OutputPort *DynParaLoop::getOutputPort(const std::string& name) const throw(Exception)
169 if(name==NAME_OF_SPLITTED_SEQ_OUT)
170 return (OutputPort *)&_splittedPort;
171 return ComposedNode::getOutputPort(name);
174 bool DynParaLoop::isPlacementPredictableB4Run() const
179 Node *DynParaLoop::edRemoveNode()
183 ComposedNode::edRemoveChild(_node);
189 Node *DynParaLoop::edRemoveInitNode()
193 ComposedNode::edRemoveChild(_initNode);
199 void DynParaLoop::edRemoveChild(Node *node) throw(Exception)
201 ComposedNode::edRemoveChild(node);
208 std::set<Node *> DynParaLoop::edGetDirectDescendants() const
214 ret.insert(_initNode);
218 std::list<InputPort *> DynParaLoop::getSetOfInputPort() const
220 list<InputPort *> ret=ComposedNode::getSetOfInputPort();
221 ret.push_back((InputPort *)&_nbOfBranches);
225 unsigned DynParaLoop::getNumberOfBranchesCreatedDyn() const throw(Exception)
227 if(_execNodes.empty())
228 throw Exception("ForEachLoop::getNumberOfBranches : No branches created dynamically ! - ForEachLoop needs to run or to be runned to call getNumberOfBranches");
230 return _execNodes.size();
233 Node *DynParaLoop::getChildByShortName(const std::string& name) const throw(Exception)
236 if(name==_node->getName())
239 if(name==_initNode->getName())
241 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
242 throw Exception(what);
245 Node *DynParaLoop::getChildByNameExec(const std::string& name, unsigned id) const throw(Exception)
247 if(id>=getNumberOfBranchesCreatedDyn())
248 throw Exception("ForEachLoop::getChildByNameExec : invalid id - too large compared with dynamically created branches.");
250 if(name==_node->getName())
251 return _execNodes[id];
253 if(name==_initNode->getName())
254 return _execInitNodes[id];
255 std::string what("node "); what+= name ; what+=" is not a child of DynParaLoop node "; what += getName();
256 throw Exception(what);
259 void DynParaLoop::cleanDynGraph()
261 for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++)
264 for(vector<Node *>::iterator iter2=_execInitNodes.begin();iter2!=_execInitNodes.end();iter2++)
270 * This method applies on newly cloned on exec nodes (_execNodes/_execInitNodes)
271 * the setting of input ports coming from outside of 'this'
273 void DynParaLoop::prepareInputsFromOutOfScope(int branchNb)
275 set< InPort * > portsToSetVals=getAllInPortsComingFromOutsideOfCurrentScope();
276 portsToSetVals.erase(&_nbOfBranches);//_nbOfBranches inport is not a candidate of dynamically duplicated inport.
277 for(set< InPort * >::iterator iter=portsToSetVals.begin();iter!=portsToSetVals.end();iter++)
279 InputPort *curPortCasted=(InputPort *) *iter;//Cast granted by ForEachLoop::buildDelegateOf(InPort)
280 void *val=curPortCasted->get();
281 InputPort *portToSet=getDynInputPortByAbsName(branchNb,getInPortName(*iter),true);
282 if(portToSet)//portToSet==0 in case of portToSet==_splitterNode._dataPortToDispatch of ForEach
284 portToSet->put((const void *)val);
285 portToSet->edNotifyReferencedBy(0);//This is to indicate that somewhere somebody deals with this inputport
286 //even if no direct physical link exists. This exclusively for _execNodes[branchNb]::init on the next turn of loop.
291 void DynParaLoop::putValueOnBranch(Any *val, unsigned branchId, bool first)
293 bool isDispatched = false;
294 set<InPort *> inPrtLkdWthSplttdPrt=_splittedPort.edSetInPort();
295 for(set<InPort *>::iterator iter=inPrtLkdWthSplttdPrt.begin();iter!=inPrtLkdWthSplttdPrt.end();iter++)
297 std::string portNameOnCurPrt=getPortName(*iter);
298 InputPort *portOnGivenBranch=getDynInputPortByAbsName(branchId,portNameOnCurPrt,first);//Cast granted because impossible to have cross protocol with _splittedPort
299 //see OptimizerLoop::buildDelegateOf
300 if(portOnGivenBranch)
303 portOnGivenBranch->edNotifyReferencedBy(0);
304 InputPort *traducer=getRuntime()->adapt(portOnGivenBranch,
305 Runtime::RUNTIME_ENGINE_INTERACTION_IMPL_NAME,_splittedPort.edGetType());
306 traducer->put((const void *)val);
308 if(traducer!=portOnGivenBranch)
314 Any *tmp=val->clone();
315 _splittedPort.setValue(tmp);
320 DynParaLoop::TypeOfNode DynParaLoop::getIdentityOfNotifyerNode(const Node *node, unsigned& id)
323 for(vector<Node *>::iterator iter=_execNodes.begin();iter!=_execNodes.end();iter++,id++)
327 for(vector<Node *>::iterator iter2=_execInitNodes.begin();iter2!=_execInitNodes.end();iter2++,id++)
332 bool DynParaLoop::isMultiplicitySpecified(unsigned& value) const
334 if(_nbOfBranches.edIsManuallyInitialized())
335 if(_nbOfBranches.edGetNumberOfLinks()==0)
337 value=_nbOfBranches.getIntValue();
343 void DynParaLoop::forceMultiplicity(unsigned value)
345 _nbOfBranches.edRemoveAllLinksLinkedWithMe();
346 _nbOfBranches.edInit((int)value);
349 void DynParaLoop::buildDelegateOf(InPort * & port, OutPort *initialStart, const std::set<ComposedNode *>& pointsOfView)
351 string typeOfPortInstance=port->getNameOfTypeOfCurrentInstance();
352 if(typeOfPortInstance!=InputPort::NAME)
353 throw Exception("DynParaLoop::buildDelegateOf : A link with datastream end inside DynParaLoop this is not possible");
356 void DynParaLoop::buildDelegateOf(std::pair<OutPort *, OutPort *>& port, InPort *finalTarget, const std::set<ComposedNode *>& pointsOfView)
359 if(isInMyDescendance(port.first->getNode())==_initNode)
360 throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : a link starting from init node can't leave the scope of ForEachLoop node it belongs to.");
361 if(port.first==&_splittedPort)
362 throw Exception("DynParaLoop::buildDelegateOf : uncorrect ForEach link : splitted port must be link within the scope of ForEachLoop node it belongs to.");
366 * \note : For a given name 'name' of port in absolute form from this, returns the corresponding InputPort instance of the
367 * port for the branch # 'branchNb'. The port can be part of _node or _initNode if it exists (if 'initNodeAdmitted' is true).
368 * \b WARNING : no check performed on 'branchNb' value to see if it is compatible with size of '_execNodes'.
369 * This method is called to dispatch value on each InputPort linked to this->._splitterNode._splittedPort
371 InputPort *DynParaLoop::getDynInputPortByAbsName(int branchNb, const std::string& name, bool initNodeAdmitted)
373 string portName, nodeName;
374 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,true);
375 Node *staticChild = getChildByName(nodeName);
376 Node *desc=isInMyDescendance(staticChild);
379 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
380 return _execNodes[branchNb]->getInputPort(portName);
382 else if(desc==_initNode)
385 splitNamesBySep(name,Node::SEP_CHAR_IN_PORT,nodeName,portName,false);
386 return _execInitNodes[branchNb]->getInputPort(portName);