47 bool ownsPublishedNodeClasses =
false;
52 triggerNodeClass = compiler->
getNodeClass(
"vuo.event.spinOffEvent2");
58 vector<VuoPortClass *> inputPortClasses;
59 vector<VuoPortClass *> outputPortClasses(1, triggerPortClass->
getBase());
60 VuoNodeClass *baseNodeClass =
new VuoNodeClass(
"vuo.event.spinOffEvent2", refreshPortClass, inputPortClasses, outputPortClasses);
67 if (! (publishedInputPorts.empty() && publishedOutputPorts.empty()) )
74 ownsPublishedNodeClasses =
false;
83 ownsPublishedNodeClasses =
true;
93 initializeInstance(composition, potentialCables, publishedInputNode, publishedOutputNode, publishedInputTriggerNode, ownsPublishedNodeClasses,
94 manuallyFirableTriggerNode);
119 void VuoCompilerGraph::initializeInstance(
VuoCompilerComposition *composition, set<VuoCompilerCable *> potentialCables,
121 VuoCompilerNode *publishedInputTriggerNode,
bool ownsPublishedNodeClasses,
124 this->publishedInputNode = publishedInputNode;
125 this->publishedOutputNode = publishedOutputNode;
126 this->ownsPublishedNodeClasses = ownsPublishedNodeClasses;
127 this->publishedInputTrigger =
nullptr;
131 set<VuoNode *> nodesIncludingInvalid = composition->
getBase()->
getNodes();
132 set<VuoNode *> nodesToAnalyze;
133 for (
VuoNode *node : nodesIncludingInvalid)
134 if (node->hasCompiler())
135 nodesToAnalyze.insert(node);
137 if (publishedInputNode && publishedOutputNode)
141 nodesToAnalyze.insert(publishedInputNode->
getBase());
142 nodesToAnalyze.insert(publishedOutputNode->
getBase());
146 nodesToAnalyze.insert(publishedInputTriggerNode->
getBase());
149 this->publishedInputTrigger = static_cast<VuoCompilerTriggerPort *>(publishedInputTriggerPort->
getCompiler());
154 nodesToAnalyze.insert(manuallyFirableTriggerNode->
getBase());
157 this->manuallyFirableTrigger = static_cast<VuoCompilerTriggerPort *>(manuallyFirableTriggerPort->
getCompiler());
161 set<VuoPort *> potentialCableInputs;
163 if (cable->carriesData())
164 potentialCableInputs.insert(cable->getBase()->getToPort());
166 set<VuoCable *> cablesIncludingInvalidAndPublished = composition->
getBase()->
getCables();
167 set<VuoCable *> cablesToAnalyze;
168 for (
VuoCable *cable : cablesIncludingInvalidAndPublished)
170 if ((cable->getFromPort() && cable->getToPort())
171 && (cable->getFromPort()->hasCompiler() && cable->getToPort()->hasCompiler())
172 && ! (cable->hasCompiler() && cable->getCompiler()->carriesData() &&
173 potentialCableInputs.find(cable->getToPort()) != potentialCableInputs.end()) )
175 if (cable->isPublished())
176 publishedCables.insert(cable);
178 cablesToAnalyze.insert(cable);
186 if (cable->getBase()->isPublished())
187 publishedCables.insert(cable->getBase());
189 cablesToAnalyze.insert(cable->getBase());
196 for (
VuoCable *cable : publishedCables)
203 if (cable->isPublishedInputCable())
205 size_t publishedPortIndex = std::distance(publishedInputPorts.begin(), std::find(publishedInputPorts.begin(), publishedInputPorts.end(), cable->getFromPort()));
207 fromNode = publishedInputNode->
getBase();
208 fromPort = getOutputPortOnPublishedInputNode(publishedPortIndex);
209 toNode = cable->getToNode();
210 toPort = cable->getToPort();
214 size_t publishedPortIndex = std::distance(publishedOutputPorts.begin(), std::find(publishedOutputPorts.begin(), publishedOutputPorts.end(), cable->getToPort()));
216 fromNode = cable->getFromNode();
217 fromPort = cable->getFromPort();
218 toNode = publishedOutputNode->
getBase();
225 cablesToAnalyze.insert(replacement->
getBase());
230 if (publishedInputTrigger)
234 publishedInputNode, static_cast<VuoCompilerPort *>(toPort->
getCompiler()),
false);
235 cablesToAnalyze.insert(spinOffCable->
getBase());
243 if (toNode && toPort)
247 cablesToAnalyze.insert(spinOffCable->
getBase());
251 for (
VuoNode *node : nodesToAnalyze)
252 nodes.insert(node->getCompiler());
254 makeTriggers(nodesToAnalyze);
255 makeVerticesAndEdges(cablesToAnalyze);
256 makeDownstreamVertices();
258 makeVertexDistances();
259 makeDownstreamNodesViaDataOnlyTransmission(nodesToAnalyze, cablesToAnalyze);
267 VuoCompilerNode *publishedInputTriggerNode = nodeForTrigger[publishedInputTrigger];
269 if (ownsPublishedNodeClasses)
276 delete publishedInputNode;
277 delete publishedOutputNode;
278 delete publishedInputTriggerNode;
284 void VuoCompilerGraph::makeTriggers(set<VuoNode *> nodes)
288 for (
VuoPort *port : node->getOutputPorts())
293 nodeForTrigger[trigger] = node->getCompiler();
294 triggers.push_back(trigger);
303 void VuoCompilerGraph::makeVerticesAndEdges(
const set<VuoCable *> &cables)
307 set<Vertex> allVertices;
310 VuoCompilerPort *fromPort = cable->getFromPort() ? static_cast<VuoCompilerPort *>(cable->getFromPort()->getCompiler()) :
nullptr;
314 Vertex vertex = (fromTrigger ? Vertex(fromTrigger, toNode) : Vertex(fromNode, toNode));
316 set<Vertex>::iterator vertexIter = allVertices.find(vertex);
317 if (vertexIter != allVertices.end())
319 vertex.cableBundle = (*vertexIter).cableBundle;
320 allVertices.erase(vertexIter);
322 vertex.cableBundle.insert(cable->getCompiler());
324 allVertices.insert(vertex);
331 set<Vertex> verticesToVisit;
332 set<Edge> edgesVisited;
334 for (set<Vertex>::iterator j = allVertices.begin(); j != allVertices.end(); ++j)
335 if ((*j).fromTrigger == trigger)
336 verticesToVisit.insert(*j);
338 map<VuoCompilerNode *, set<Vertex> > outgoingVerticesForNode;
339 for (set<Vertex>::iterator j = allVertices.begin(); j != allVertices.end(); ++j)
340 outgoingVerticesForNode[(*j).fromNode].insert(*j);
342 while (! verticesToVisit.empty())
344 Vertex vertex = *verticesToVisit.begin();
345 if (find(vertices[trigger].begin(), vertices[trigger].end(), vertex) == vertices[trigger].end())
346 vertices[trigger].push_back(vertex);
347 verticesToVisit.erase(verticesToVisit.begin());
349 set<Vertex> potentialOutgoingVertices = outgoingVerticesForNode[vertex.toNode];
350 for (set<Vertex>::iterator j = potentialOutgoingVertices.begin(); j != potentialOutgoingVertices.end(); ++j)
352 Vertex outgoingVertex = *j;
354 if (
mayTransmit(vertex.cableBundle, outgoingVertex.cableBundle))
356 Edge outgoingEdge(vertex, outgoingVertex);
357 if (edgesVisited.find(outgoingEdge) == edgesVisited.end())
359 edges[trigger].insert(outgoingEdge);
360 edgesVisited.insert(outgoingEdge);
362 verticesToVisit.insert(outgoingVertex);
374 void VuoCompilerGraph::makeDownstreamVerticesWithInclusionRule(
VuoCompilerTriggerPort *trigger, std::function<
bool(Edge)> includeEdge,
375 map<Vertex, set<Vertex> > &_downstreamVertices,
376 set<Vertex> &_repeatedVertices)
378 list<Vertex> verticesToVisit;
380 for (Vertex vertex : vertices[trigger])
381 if (vertex.fromTrigger == trigger)
382 verticesToVisit.push_back(vertex);
384 map<Vertex, set<Vertex> > outgoingVerticesFromVertex;
385 for (Edge edge : edges[trigger])
386 if (includeEdge(edge))
387 outgoingVerticesFromVertex[edge.fromVertex].insert(edge.toVertex);
389 while (! verticesToVisit.empty())
392 Vertex currentVertex = verticesToVisit.back();
394 set<Vertex> currentDownstreamVertices;
395 bool areDownstreamVerticesComplete =
true;
398 set<Vertex> outgoingVertices = outgoingVerticesFromVertex[currentVertex];
399 for (set<Vertex>::iterator j = outgoingVertices.begin(); j != outgoingVertices.end(); ++j)
401 Vertex outgoingVertex = *j;
402 currentDownstreamVertices.insert(outgoingVertex);
404 if (_downstreamVertices.find(outgoingVertex) != _downstreamVertices.end())
407 set<Vertex> furtherDownstreamVertices = _downstreamVertices[outgoingVertex];
408 currentDownstreamVertices.insert( furtherDownstreamVertices.begin(), furtherDownstreamVertices.end() );
412 if (find(verticesToVisit.begin(), verticesToVisit.end(), outgoingVertex) != verticesToVisit.end())
415 _repeatedVertices.insert(outgoingVertex);
420 verticesToVisit.push_back(outgoingVertex);
421 areDownstreamVerticesComplete =
false;
426 if (areDownstreamVerticesComplete)
428 _downstreamVertices[currentVertex] = currentDownstreamVertices;
429 verticesToVisit.pop_back();
435 set<Vertex> repeatedVerticesCopy = _repeatedVertices;
436 for (Vertex vertex : repeatedVerticesCopy)
437 if (_downstreamVertices[vertex].find(vertex) == _downstreamVertices[vertex].end())
438 _repeatedVertices.erase(vertex);
444 void VuoCompilerGraph::makeDownstreamVertices(
void)
446 auto includeAllEdges = [] (Edge edge) {
return true; };
450 makeDownstreamVerticesWithInclusionRule(trigger, includeAllEdges, downstreamVertices[trigger], repeatedVertices[trigger]);
452 if (repeatedVertices[trigger].empty())
453 repeatedVertices.erase(trigger);
463 if (publishedOutputNode)
467 for (
const map<Vertex, set<Vertex> >::value_type &i : downstreamVertices[trigger])
469 if (i.first.toNode != publishedOutputNode && i.second.empty())
471 Vertex leafVertex = i.first;
473 VuoPort *toPort = getGatherPortOnPublishedOutputNode();
475 publishedOutputNode, static_cast<VuoCompilerPort *>(toPort->
getCompiler()),
false);
477 Vertex gatherVertex(leafVertex.toNode, publishedOutputNode);
478 gatherVertex.cableBundle.insert(gather);
480 Edge gatherEdge(leafVertex, gatherVertex);
482 vertices[trigger].push_back(gatherVertex);
483 edges[trigger].insert(gatherEdge);
484 downstreamVertices[trigger][leafVertex].insert(gatherVertex);
494 void VuoCompilerGraph::sortVertices(
void)
496 for (map<
VuoCompilerTriggerPort *, vector<Vertex> >::iterator i = vertices.begin(); i != vertices.end(); ++i)
499 vector<Vertex> verticesToSort = i->second;
501 map<Vertex, set<Vertex> > dependentVertices;
502 list<Vertex> verticesToVisit;
503 map<Vertex, bool> verticesCompleted;
505 for (vector<Vertex>::iterator j = verticesToSort.begin(); j != verticesToSort.end(); ++j)
506 if ((*j).fromTrigger == trigger)
507 verticesToVisit.push_back(*j);
509 map<VuoCompilerNode *, set<Vertex> > outgoingVerticesForNode;
510 for (vector<Vertex>::iterator j = verticesToSort.begin(); j != verticesToSort.end(); ++j)
511 outgoingVerticesForNode[(*j).fromNode].insert(*j);
513 while (! verticesToVisit.empty())
516 Vertex currentVertex = verticesToVisit.back();
518 set<Vertex> currentDependentVertices;
519 bool areDependentVerticesComplete =
true;
525 set<Vertex> outgoingVertices;
526 set<Vertex> potentialOutgoingVertices = outgoingVerticesForNode[currentVertex.toNode];
527 for (set<Vertex>::iterator j = potentialOutgoingVertices.begin(); j != potentialOutgoingVertices.end(); ++j)
529 Vertex outgoingVertex = *j;
530 if (downstreamVertices[trigger][outgoingVertex].find(currentVertex) == downstreamVertices[trigger][outgoingVertex].end())
531 outgoingVertices.insert(outgoingVertex);
534 outgoingVertices.clear();
539 for (set<Vertex>::iterator j = outgoingVertices.begin(); j != outgoingVertices.end(); ++j)
541 Vertex outgoingVertex = *j;
542 currentDependentVertices.insert(outgoingVertex);
544 if (verticesCompleted[outgoingVertex])
547 currentDependentVertices.insert( dependentVertices[outgoingVertex].begin(), dependentVertices[outgoingVertex].end() );
549 else if (find(verticesToVisit.begin(), verticesToVisit.end(), outgoingVertex) == verticesToVisit.end())
552 verticesToVisit.push_back(outgoingVertex);
553 areDependentVerticesComplete =
false;
557 if (areDependentVerticesComplete)
559 dependentVertices[currentVertex] = currentDependentVertices;
560 verticesToVisit.pop_back();
561 verticesCompleted[currentVertex] =
true;
566 vector< pair<size_t, Vertex> > verticesAndDependents;
567 for (map<Vertex, set<Vertex> >::iterator j = dependentVertices.begin(); j != dependentVertices.end(); ++j)
568 verticesAndDependents.push_back( make_pair(j->second.size(), j->first) );
569 sort(verticesAndDependents.begin(), verticesAndDependents.end());
571 vector<Vertex> sortedVertices;
572 for (vector< pair<size_t, Vertex> >::reverse_iterator j = verticesAndDependents.rbegin(); j != verticesAndDependents.rend(); ++j)
573 sortedVertices.push_back((*j).second);
575 vertices[trigger] = sortedVertices;
582 void VuoCompilerGraph::makeVertexDistances(
void)
584 for (map<
VuoCompilerTriggerPort *, vector<Vertex> >::iterator i = vertices.begin(); i != vertices.end(); ++i)
587 vector<Vertex> verticesDownstream = i->second;
589 map<VuoCompilerNode *, set<Vertex> > incomingVerticesForNode;
590 for (vector<Vertex>::iterator j = verticesDownstream.begin(); j != verticesDownstream.end(); ++j)
591 incomingVerticesForNode[(*j).toNode].insert(*j);
594 for (vector<Vertex>::iterator j = verticesDownstream.begin(); j != verticesDownstream.end(); ++j)
597 if (vertex.fromTrigger == trigger)
599 vertexDistanceFromTrigger[trigger][vertex] = 1;
600 triggerMustTransmitToVertex[trigger][vertex] =
true;
605 for (vector<Vertex>::iterator j = verticesDownstream.begin(); j != verticesDownstream.end(); ++j)
608 if (vertex.fromTrigger != trigger)
610 size_t minDistance = verticesDownstream.size();
611 bool anyMustTransmit =
false;
612 for (set<Vertex>::iterator k = incomingVerticesForNode[vertex.fromNode].begin(); k != incomingVerticesForNode[vertex.fromNode].end(); ++k)
614 Vertex upstreamVertex = *k;
616 minDistance = min(vertexDistanceFromTrigger[trigger][upstreamVertex], minDistance);
617 bool currMustTransmit = triggerMustTransmitToVertex[trigger][upstreamVertex] && mustTransmit(upstreamVertex, trigger);
618 anyMustTransmit = currMustTransmit || anyMustTransmit;
621 vertexDistanceFromTrigger[trigger][vertex] = minDistance + 1;
622 triggerMustTransmitToVertex[trigger][vertex] = anyMustTransmit;
631 void VuoCompilerGraph::makeDownstreamNodesViaDataOnlyTransmission(set<VuoNode *> nodes, set<VuoCable *> cables)
638 map<VuoCompilerNode *, set<VuoCompilerNode *> > remainingIncomingNodes;
639 map<VuoCompilerNode *, set<VuoCompilerNode *> > remainingOutgoingNodes;
642 VuoCompilerPort *fromPort = cable->getFromPort() ? static_cast<VuoCompilerPort *>(cable->getFromPort()->getCompiler()) :
nullptr;
644 if (fromTrigger || ! cable->getCompiler()->carriesData())
652 remainingOutgoingNodes[fromNode].insert(toNode);
654 remainingIncomingNodes[toNode].insert(fromNode);
657 map<VuoCompilerNode *, set<VuoCompilerNode *> > outgoingNodes = remainingOutgoingNodes;
659 set<VuoCompilerNode *> nodesToVisit;
663 remainingIncomingNodes.find(node->getCompiler()) == remainingIncomingNodes.end() &&
664 remainingOutgoingNodes.find(node->getCompiler()) != remainingOutgoingNodes.end())
665 nodesToVisit.insert(node->getCompiler());
668 vector<VuoCompilerNode *> sortedNodesAllowingDataOnlyTransmission;
669 while (! nodesToVisit.empty())
672 nodesToVisit.erase(nodesToVisit.begin());
674 sortedNodesAllowingDataOnlyTransmission.push_back(node);
676 set<VuoCompilerNode *> outgoingNodesCopy = remainingOutgoingNodes[node];
679 remainingIncomingNodes[outgoingNode].erase(node);
680 remainingOutgoingNodes[node].erase(outgoingNode);
682 if (remainingIncomingNodes[outgoingNode].empty())
683 nodesToVisit.insert(outgoingNode);
689 for (
int firstIndex = sortedNodesAllowingDataOnlyTransmission.size() - 1; firstIndex >= 0; --firstIndex)
691 VuoCompilerNode *firstNode = sortedNodesAllowingDataOnlyTransmission[firstIndex];
693 for (
size_t possiblyDownstreamIndex = firstIndex + 1; possiblyDownstreamIndex < sortedNodesAllowingDataOnlyTransmission.size(); ++possiblyDownstreamIndex)
695 VuoCompilerNode *possiblyDownstreamNode = sortedNodesAllowingDataOnlyTransmission[possiblyDownstreamIndex];
697 if (outgoingNodes[firstNode].find(possiblyDownstreamNode) != outgoingNodes[firstNode].end())
699 vector<VuoCompilerNode *> nodesToAdd = downstreamNodesViaDataOnlyTransmission[possiblyDownstreamNode];
700 nodesToAdd.insert(nodesToAdd.begin(), possiblyDownstreamNode);
703 if (find(downstreamNodesViaDataOnlyTransmission[firstNode].begin(), downstreamNodesViaDataOnlyTransmission[firstNode].end(), nodeToAdd) == downstreamNodesViaDataOnlyTransmission[firstNode].end())
704 downstreamNodesViaDataOnlyTransmission[firstNode].push_back(nodeToAdd);
716 bool VuoCompilerGraph::mustTransmit(
const set<VuoCompilerCable *> &fromCables,
const set<VuoCompilerCable *> &toCables)
718 bool fromCablesMustTransmit =
false;
721 VuoPort *inputPort = cable->getBase()->getToPort();
724 fromCablesMustTransmit =
true;
729 bool toCablesMayTransmit =
false;
732 VuoPort *outputPort = cable->getBase()->getFromPort();
735 toCablesMayTransmit =
true;
740 return fromCablesMustTransmit && toCablesMayTransmit;
748 set<VuoCompilerCable *> cablesBetweenFromNodeAndToNode = vertex.cableBundle;
750 set<VuoCompilerCable *> cablesOutOfToNode;
751 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
753 Vertex otherVertex = *i;
754 if (vertex.toNode == otherVertex.fromNode)
755 cablesOutOfToNode.insert(otherVertex.cableBundle.begin(), otherVertex.cableBundle.end());
758 return mustTransmit(cablesBetweenFromNodeAndToNode, cablesOutOfToNode);
770 bool fromCablesMayTransmit =
false;
773 VuoPort *inputPort = cable->getBase()->getToPort();
776 fromCablesMayTransmit =
true;
781 bool toCablesMayTransmit =
false;
784 VuoPort *outputPort = cable->getBase()->getFromPort();
787 toCablesMayTransmit =
true;
792 return fromCablesMayTransmit && toCablesMayTransmit;
800 set<VuoCompilerCable *> cablesBetweenFromNodeAndToNode = vertex.cableBundle;
802 set<VuoCompilerCable *> cablesOutOfToNode;
803 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
805 Vertex otherVertex = *i;
806 if (vertex.toNode == otherVertex.fromNode)
807 cablesOutOfToNode.insert(otherVertex.cableBundle.begin(), otherVertex.cableBundle.end());
810 return mayTransmit(cablesBetweenFromNodeAndToNode, cablesOutOfToNode);
818 set<VuoCompilerCable *> incomingCables;
819 set<VuoCompilerCable *> outgoingCables;
821 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
825 if (vertex.toNode == node)
826 incomingCables.insert( vertex.cableBundle.begin(), vertex.cableBundle.end() );
827 if (vertex.fromNode == node)
828 outgoingCables.insert( vertex.cableBundle.begin(), vertex.cableBundle.end() );
831 return mayTransmit(incomingCables, outgoingCables);
839 if (vertexMayTransmit[trigger].empty() && ! vertices[trigger].empty())
840 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
841 vertexMayTransmit[trigger][(*i).fromNode][(*i).toNode] =
true;
843 return vertexMayTransmit[trigger][fromNode][toNode];
867 auto foundIter = nodeForTrigger.find(trigger);
868 if (foundIter != nodeForTrigger.end())
869 return foundIter->second;
890 return publishedInputNode;
900 return publishedOutputNode;
908 return publishedInputTrigger;
924 VuoPort * VuoCompilerGraph::getOutputPortOnPublishedInputNode(
size_t publishedInputPortIndex)
944 VuoPort * VuoCompilerGraph::getGatherPortOnPublishedOutputNode(
void)
956 return manuallyFirableTrigger;
965 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
966 if ((*i).fromNode == fromNode)
977 map<VuoCompilerTriggerPort *, map<VuoCompilerNode *, size_t> >::iterator triggerIter = numVerticesWithToNode.find(trigger);
978 if (triggerIter != numVerticesWithToNode.end())
980 map<VuoCompilerNode *, size_t>::iterator nodeIter = triggerIter->second.find(toNode);
981 if (nodeIter != triggerIter->second.end())
982 return nodeIter->second;
985 size_t numVertices = 0;
986 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
987 if ((*i).toNode == toNode)
990 numVerticesWithToNode[trigger][toNode] = numVertices;
1007 if (! chains.empty())
1013 vector< vector<VuoCompilerNode *> > chainsInProgress;
1014 set<VuoCompilerNode *> nodesAdded;
1015 bool skippedPublishedOutputNode =
false;
1016 for (vector<Vertex>::iterator j = vertices[trigger].begin(); j != vertices[trigger].end(); ++j)
1019 bool addedToChain =
false;
1021 if (nodesAdded.find(vertex.toNode) != nodesAdded.end())
1024 if (vertex.toNode == publishedOutputNode)
1026 skippedPublishedOutputNode =
true;
1030 nodesAdded.insert(vertex.toNode);
1032 if (vertex.fromNode)
1034 if (getNumVerticesWithFromNode(vertex.fromNode, trigger) == 1 &&
1035 getNumVerticesWithToNode(vertex.toNode, trigger) == 1)
1037 for (
int k = 0; k < chainsInProgress.size(); ++k)
1040 if (lastNodeInChain == vertex.fromNode)
1043 chainsInProgress[k].push_back(vertex.toNode);
1044 addedToChain =
true;
1054 chainsInProgress.push_back( vector<VuoCompilerNode *>(1, vertex.toNode) );
1059 for (vector< vector<VuoCompilerNode *> >::iterator j = chainsInProgress.begin(); j != chainsInProgress.end(); ++j)
1061 vector<VuoCompilerNode *> chainNodes = *j;
1063 chains[trigger].push_back(chain);
1067 map<VuoCompilerNode *, bool> nodesSeen;
1068 for (vector<Vertex>::iterator j = vertices[trigger].begin(); j != vertices[trigger].end(); ++j)
1071 if (nodesSeen[node])
1073 nodesSeen[node] =
true;
1078 chains[trigger].push_back(chain);
1083 if (skippedPublishedOutputNode)
1086 chains[trigger].push_back(chain);
1098 set<VuoCompilerNode *> downstreamNodes;
1099 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
1100 if ((*i).fromTrigger == trigger)
1101 downstreamNodes.insert((*i).toNode);
1103 return vector<VuoCompilerNode *>(downstreamNodes.begin(), downstreamNodes.end());
1111 set<VuoCompilerNode *> downstreamNodes;
1112 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
1113 if ((*i).fromNode == node)
1114 downstreamNodes.insert((*i).toNode);
1116 return vector<VuoCompilerNode *>(downstreamNodes.begin(), downstreamNodes.end());
1124 map<VuoCompilerTriggerPort *, vector<VuoCompilerNode *> >::iterator triggerIter = downstreamNodesForTrigger.find(trigger);
1125 if (triggerIter != downstreamNodesForTrigger.end())
1126 return triggerIter->second;
1128 set<VuoCompilerNode *> downstreamNodes;
1130 downstreamNodes.insert(immediatelyDownstreamNodes.begin(), immediatelyDownstreamNodes.end());
1132 for (vector<VuoCompilerNode *>::iterator i = immediatelyDownstreamNodes.begin(); i != immediatelyDownstreamNodes.end(); ++i)
1135 downstreamNodes.insert(furtherDownstreamNodes.begin(), furtherDownstreamNodes.end());
1138 vector<VuoCompilerNode *> downstreamNodesVector(downstreamNodes.begin(), downstreamNodes.end());
1139 downstreamNodesForTrigger[trigger] = downstreamNodesVector;
1140 return downstreamNodesVector;
1148 map<VuoCompilerTriggerPort *, map<VuoCompilerNode *, vector<VuoCompilerNode *> > >::iterator triggerIter = downstreamNodesForNode.find(trigger);
1149 if (triggerIter != downstreamNodesForNode.end())
1151 map<VuoCompilerNode *, vector<VuoCompilerNode *> >::iterator nodeIter = triggerIter->second.find(node);
1152 if (nodeIter != triggerIter->second.end())
1153 return nodeIter->second;
1156 set<Vertex> verticesWithDownstreamNodes;
1157 for (vector<Vertex>::iterator i = vertices[trigger].begin(); i != vertices[trigger].end(); ++i)
1160 if (vertex.fromNode == node)
1162 verticesWithDownstreamNodes.insert(vertex);
1163 set<Vertex> downstream = downstreamVertices[trigger][vertex];
1164 verticesWithDownstreamNodes.insert(downstream.begin(), downstream.end());
1168 set<VuoCompilerNode *> downstreamNodes;
1169 for (set<Vertex>::iterator i = verticesWithDownstreamNodes.begin(); i != verticesWithDownstreamNodes.end(); ++i)
1170 downstreamNodes.insert((*i).toNode);
1172 vector<VuoCompilerNode *> downstreamNodesVector(downstreamNodes.begin(), downstreamNodes.end());
1173 downstreamNodesForNode[trigger][node] = downstreamNodesVector;
1174 return downstreamNodesVector;
1183 return downstreamNodesViaDataOnlyTransmission[node];
1193 set<VuoCompilerCable *> outgoingCables;
1198 if (cable->getToNode() && cable->getToNode()->hasCompiler())
1199 outgoingCables.insert(cable->getCompiler());
1204 for (Vertex vertex : kv.second)
1207 outgoingCables.insert(cable);
1209 return outgoingCables;
1217 set<VuoCompilerNode *> nodesTransmittingDataOnly;
1218 set<VuoCompilerNode *> nodesDownstreamOfAnother;
1220 for (
const map<
VuoCompilerNode *, vector<VuoCompilerNode *> >::value_type &i : downstreamNodesViaDataOnlyTransmission)
1222 nodesTransmittingDataOnly.insert(i.first);
1223 nodesDownstreamOfAnother.insert(i.second.begin(), i.second.end());
1226 set<VuoCompilerNode *> nodesNotDownstream;
1227 std::set_difference(nodesTransmittingDataOnly.begin(), nodesTransmittingDataOnly.end(),
1228 nodesDownstreamOfAnother.begin(), nodesDownstreamOfAnother.end(),
1229 std::inserter(nodesNotDownstream, nodesNotDownstream.end()));
1230 return nodesNotDownstream;
1240 minThreadsNeeded = 1;
1241 maxThreadsNeeded = 1;
1248 for (vector<VuoCompilerTriggerDescription *>::iterator k = triggerDescriptions.begin(); k != triggerDescriptions.end(); ++k)
1253 int minThreadsNeededForSubcomposition, maxThreadsNeededForSubcomposition;
1254 (*k)->getWorkerThreadsNeeded(minThreadsNeededForSubcomposition, maxThreadsNeededForSubcomposition);
1255 minThreadsNeeded = max(minThreadsNeeded, minThreadsNeededForSubcomposition + 1);
1256 maxThreadsNeeded = max(maxThreadsNeeded, maxThreadsNeededForSubcomposition + 1);
1271 vector<VuoCompilerChain *> chainsForTrigger =
getChains()[trigger];
1272 map<VuoCompilerChain *, pair<int, int> > threadsNeededForChain;
1273 for (vector<VuoCompilerChain *>::iterator i = chainsForTrigger.begin(); i != chainsForTrigger.end(); ++i)
1277 int minThreadsNeededForChain, maxThreadsNeededForChain;
1280 threadsNeededForChain[chain] = make_pair(minThreadsNeededForChain, maxThreadsNeededForChain);
1284 map<VuoCompilerChain *, set<VuoCompilerChain *> > chainsDownstream;
1285 for (vector<VuoCompilerChain *>::iterator i = chainsForTrigger.begin(); i != chainsForTrigger.end(); ++i)
1290 vector<VuoCompilerNode *> nodesDownstream =
getNodesDownstream(lastNodeInThisChain, trigger);
1292 for (vector<VuoCompilerChain *>::iterator j = i+1; j != chainsForTrigger.end(); ++j)
1297 if (find(nodesDownstream.begin(), nodesDownstream.end(), firstNodeInOtherChain) != nodesDownstream.end())
1298 chainsDownstream[chain].insert(otherChain);
1303 map<VuoCompilerChain *, set<VuoCompilerChain *> > chainsImmediatelyDownstream;
1304 map<VuoCompilerChain *, set<VuoCompilerChain *> > chainsImmediatelyUpstream;
1305 for (vector<VuoCompilerChain *>::iterator i = chainsForTrigger.begin(); i != chainsForTrigger.end(); ++i)
1312 for (vector<VuoCompilerChain *>::iterator j = i+1; j != chainsForTrigger.end(); ++j)
1317 if (find(nodesDownstream.begin(), nodesDownstream.end(), firstNodeInOtherChain) != nodesDownstream.end())
1319 chainsImmediatelyDownstream[chain].insert(otherChain);
1320 chainsImmediatelyUpstream[otherChain].insert(chain);
1326 minThreadsNeeded = 1;
1327 maxThreadsNeeded = 1;
1336 vector< pair<VuoCompilerChain *, vector<VuoCompilerChain *> > > potentialScatters;
1337 vector<VuoCompilerChain *> scatterForTrigger;
1338 for (vector<VuoCompilerChain *>::iterator i = chainsForTrigger.begin(); i != chainsForTrigger.end(); ++i)
1339 if (chainsImmediatelyUpstream.find(*i) == chainsImmediatelyUpstream.end())
1340 scatterForTrigger.push_back(*i);
1341 potentialScatters.push_back( make_pair((
VuoCompilerChain *)NULL, scatterForTrigger) );
1344 for (vector<VuoCompilerChain *>::iterator i = chainsForTrigger.begin(); i != chainsForTrigger.end(); ++i)
1346 vector<VuoCompilerChain *> scatterForChain(chainsImmediatelyDownstream[*i].begin(), chainsImmediatelyDownstream[*i].end());
1347 potentialScatters.push_back( make_pair(*i, scatterForChain) );
1350 map<VuoCompilerChain *, int> threadsNeededForScatters;
1351 for (vector< pair<
VuoCompilerChain *, vector<VuoCompilerChain *> > >::reverse_iterator i = potentialScatters.rbegin(); i != potentialScatters.rend(); ++i)
1354 vector<VuoCompilerChain *> scatterChains = (*i).second;
1358 for (
size_t j = 0; j < scatterChains.size(); ++j)
1362 for (
size_t k = j+1; k < scatterChains.size(); ++k)
1366 if (chainsDownstream[inner].find(outer) != chainsDownstream[inner].end())
1368 scatterChains.erase( scatterChains.begin() + j-- );
1372 if (chainsDownstream[outer].find(inner) != chainsDownstream[outer].end())
1373 scatterChains.erase( scatterChains.begin() + k-- );
1378 int threadsNeededForScatter = 0;
1379 for (vector<VuoCompilerChain *>::iterator j = scatterChains.begin(); j != scatterChains.end(); ++j)
1380 threadsNeededForScatter += threadsNeededForScatters[*j];
1383 threadsNeededForScatter = max(threadsNeededForScatter, threadsNeededForChain[chain].second);
1385 threadsNeededForScatters[chain] = threadsNeededForScatter;
1389 for (map<VuoCompilerChain *, int>::iterator i = threadsNeededForScatters.begin(); i != threadsNeededForScatters.end(); ++i)
1390 maxThreadsNeeded = max(maxThreadsNeeded, i->second);
1397 for (map<
VuoCompilerChain *, pair<int, int> >::iterator i = threadsNeededForChain.begin(); i != threadsNeededForChain.end(); ++i)
1398 minThreadsNeeded = max(minThreadsNeeded, i->second.first);
1413 vector< pair<VuoCompilerTriggerPort *, size_t> > distancesForMusts;
1414 vector< pair<VuoCompilerTriggerPort *, size_t> > distancesForMays;
1416 for (map<
VuoCompilerTriggerPort *, vector<Vertex> >::iterator i = vertices.begin(); i != vertices.end(); ++i)
1419 vector<Vertex> verticesDownstream = i->second;
1421 for (vector<Vertex>::iterator j = verticesDownstream.begin(); j != verticesDownstream.end(); ++j)
1424 if (vertex.toNode == node)
1426 pair<VuoCompilerTriggerPort *, size_t> p = make_pair(trigger, vertexDistanceFromTrigger[trigger][vertex]);
1427 if (triggerMustTransmitToVertex[trigger][vertex])
1428 distancesForMusts.push_back(p);
1430 distancesForMays.push_back(p);
1435 if (! distancesForMusts.empty())
1437 sort(distancesForMusts.begin(), distancesForMusts.end(), compareTriggers);
1438 return distancesForMusts[0].first;
1440 else if (! distancesForMays.empty())
1442 sort(distancesForMays.begin(), distancesForMays.end(), compareTriggers);
1443 return distancesForMays[0].first;
1453 bool VuoCompilerGraph::compareTriggers(
const pair<VuoCompilerTriggerPort *, size_t> &lhs,
const pair<VuoCompilerTriggerPort *, size_t> &rhs)
1455 if (lhs.second == rhs.second)
1456 return lhs.first->getIdentifier() < rhs.first->getIdentifier();
1458 return lhs.second < rhs.second;
1474 if (! publishedInputTrigger)
1482 if (publishedOutputCount - publishedOutputTriggers.size() == 0)
1485 VuoPort *outputPort = getOutputPortOnPublishedInputNode(publishedInputPortIndex);
1487 set<Vertex> verticesFromPublishedInputNode;
1488 for (Vertex vertex : vertices[publishedInputTrigger])
1489 if (vertex.fromNode == publishedInputNode)
1490 verticesFromPublishedInputNode.insert(vertex);
1494 auto includeNonBlocking = [
this] (Edge edge)
1496 return (edge.fromVertex.fromTrigger == publishedInputTrigger ||
1497 mustTransmit(edge.fromVertex.cableBundle, edge.toVertex.cableBundle));
1500 if (downstreamVerticesNonBlocking.empty())
1503 makeDownstreamVerticesWithInclusionRule(publishedInputTrigger, includeNonBlocking, downstreamVerticesNonBlocking, unused);
1508 auto includeNonBlockingAndDoor = [
this] (Edge edge)
1510 return (edge.fromVertex.fromTrigger == publishedInputTrigger ||
1511 mayTransmit(edge.fromVertex.cableBundle, edge.toVertex.cableBundle));
1514 if (downstreamVerticesNonBlockingOrDoor.empty())
1517 makeDownstreamVerticesWithInclusionRule(publishedInputTrigger, includeNonBlockingAndDoor, downstreamVerticesNonBlockingOrDoor, unused);
1533 vector<Vertex> verticesToPublishedOutputNode;
1534 for (Vertex vertex : verticesFromPublishedInputNode)
1544 blockingForVertex = minBlocking(blockingForVertex, toPortBlocking);
1554 auto isVertexToPublishedOutputNode = [
this] (Vertex downstreamVertex) {
return downstreamVertex.toNode == publishedOutputNode; };
1556 vector<Vertex> verticesNonBlocking;
1557 std::copy_if(downstreamVerticesNonBlocking[vertex].begin(), downstreamVerticesNonBlocking[vertex].end(),
1558 std::back_inserter(verticesNonBlocking), isVertexToPublishedOutputNode);
1560 verticesToPublishedOutputNode.insert(verticesToPublishedOutputNode.end(), verticesNonBlocking.begin(), verticesNonBlocking.end());
1562 if (! verticesNonBlocking.empty())
1569 vector<Vertex> verticesNonBlockingOrDoor;
1570 std::copy_if(downstreamVerticesNonBlockingOrDoor[vertex].begin(), downstreamVerticesNonBlockingOrDoor[vertex].end(),
1571 std::back_inserter(verticesNonBlockingOrDoor), isVertexToPublishedOutputNode);
1573 verticesToPublishedOutputNode.insert(verticesToPublishedOutputNode.end(), verticesNonBlocking.begin(), verticesNonBlocking.end());
1575 if (! verticesNonBlockingOrDoor.empty())
1588 blocking = minBlocking(blocking, blockingForVertex);
1593 set<VuoPort *> publishedOutputPortsReached;
1594 for (Vertex vertex : verticesToPublishedOutputNode)
1599 if (publishedOutputPortsReached.size() < publishedOutputCount - publishedOutputTriggers.size())
1611 set<string> triggerNames;
1615 triggerNames.insert(currTriggerNames.begin(), currTriggerNames.end());
1618 return triggerNames;
1627 if (trigger == publishedInputTrigger)
1628 return set<string>();
1633 set<string> triggerNames;
1634 std::set_difference(outputNames.begin(), outputNames.end(),
1635 outputNamesForPublishedInputTrigger.begin(), outputNamesForPublishedInputTrigger.end(),
1636 std::inserter(triggerNames, triggerNames.begin()));
1638 return triggerNames;
1646 auto iter = publishedOutputNames.find(trigger);
1647 if (iter != publishedOutputNames.end())
1648 return iter->second;
1651 for (Vertex vertex : vertices[trigger])
1653 if (vertex.toNode == publishedOutputNode)
1658 if (toPort != getGatherPortOnPublishedOutputNode())
1664 publishedOutputNames[trigger] = names;
1687 return find(downstreamNodes.begin(), downstreamNodes.end(), node) != downstreamNodes.end();
1696 for (vector<VuoCompilerNode *>::iterator i = downstreamNodes.begin(); i != downstreamNodes.end(); ++i)
1697 if (getNumVerticesWithToNode(*i, trigger) > 1)
1710 if (isScatterAtTrigger)
1713 return areNodesPartiallyOverlappedByAnotherTrigger(downstreamNodes, trigger);
1726 if (isScatterAtNode)
1729 return areNodesPartiallyOverlappedByAnotherTrigger(downstreamNodes, trigger);
1738 bool VuoCompilerGraph::areNodesPartiallyOverlappedByAnotherTrigger(
const vector<VuoCompilerNode *> &nodes,
VuoCompilerTriggerPort *trigger)
1740 for (vector<VuoCompilerTriggerPort *>::iterator i = triggers.begin(); i != triggers.end(); ++i)
1743 if (otherTrigger == trigger)
1746 vector<VuoCompilerNode *> nodesDownstreamOfOtherTrigger =
getNodesDownstream(otherTrigger);
1747 nodesDownstreamOfOtherTrigger.push_back(nodeForTrigger[otherTrigger]);
1749 bool hasOverlappedNode =
false;
1750 bool hasNonOverlappedNode =
false;
1751 for (vector<VuoCompilerNode *>::const_iterator j = nodes.begin(); j != nodes.end(); ++j)
1755 if (find(nodesDownstreamOfOtherTrigger.begin(), nodesDownstreamOfOtherTrigger.end(), downstreamNode) != nodesDownstreamOfOtherTrigger.end())
1756 hasOverlappedNode =
true;
1758 hasNonOverlappedNode =
true;
1761 if (hasOverlappedNode && hasNonOverlappedNode)
1775 vector<VuoCompilerNode *> nodesDownstreamOfSpinOffs;
1779 vector<VuoCompilerNode *> nodesToCheck = nodesDownstreamOfTrigger;
1780 map<VuoCompilerNode *, bool> nodesChecked;
1781 while (! nodesToCheck.empty())
1784 nodesToCheck.pop_back();
1786 if (nodesChecked[node])
1788 nodesChecked[node] =
true;
1790 if (node == nodeForTrigger[publishedInputTrigger])
1800 nodesDownstreamOfSpinOffs.insert(nodesDownstreamOfSpinOffs.end(), nodesDownstream.begin(), nodesDownstream.end());
1801 nodesToCheck.insert(nodesToCheck.end(), nodesDownstream.begin(), nodesDownstream.end());
1805 sort(nodesDownstreamOfTrigger.begin(), nodesDownstreamOfTrigger.end());
1806 sort(nodesDownstreamOfSpinOffs.begin(), nodesDownstreamOfSpinOffs.end());
1809 set<VuoCompilerNode *> nodesDownstreamOfBoth;
1810 set_intersection(nodesDownstreamOfTrigger.begin(), nodesDownstreamOfTrigger.end(),
1811 nodesDownstreamOfSpinOffs.begin(), nodesDownstreamOfSpinOffs.end(),
1812 std::inserter(nodesDownstreamOfBoth, nodesDownstreamOfBoth.begin()));
1813 return ! nodesDownstreamOfBoth.empty();
1827 if (! repeatedVertices.empty())
1830 vector< set<VuoNode *> > nodesInLoops;
1831 vector< set<VuoCable *> > cablesInLoops;
1832 for (
const auto &i : repeatedVertices)
1835 for (
const Vertex &repeatedVertex : i.second)
1837 set<VuoNode *> nodesInLoop;
1838 set<VuoCable *> cablesInLoop;
1839 for (
const Vertex &otherVertex : vertices[trigger])
1841 if (downstreamVertices[trigger][repeatedVertex].find(otherVertex) != downstreamVertices[trigger][repeatedVertex].end() &&
1842 downstreamVertices[trigger][otherVertex].find(repeatedVertex) != downstreamVertices[trigger][otherVertex].end())
1844 nodesInLoop.insert(otherVertex.fromNode->getBase());
1845 nodesInLoop.insert(otherVertex.toNode->getBase());
1847 for (set<VuoCompilerCable *>::iterator m = otherVertex.cableBundle.begin(); m != otherVertex.cableBundle.end(); ++m)
1848 cablesInLoop.insert((*m)->getBase());
1851 nodesInLoops.push_back(nodesInLoop);
1852 cablesInLoops.push_back(cablesInLoop);
1857 vector< set<VuoNode *> > coalescedNodesInLoops;
1858 vector< set<VuoCable *> > coalescedCablesInLoops;
1859 for (
size_t i = 0; i < nodesInLoops.size(); ++i)
1861 bool coalesced =
false;
1862 for (
size_t j = 0; j < coalescedNodesInLoops.size(); ++j)
1864 set<VuoNode *> nodesInBoth;
1865 std::set_intersection(nodesInLoops[i].begin(), nodesInLoops[i].end(),
1866 coalescedNodesInLoops[j].begin(), coalescedNodesInLoops[j].end(),
1867 std::inserter(nodesInBoth, nodesInBoth.begin()));
1869 set<VuoCable *> cablesInBoth;
1870 std::set_intersection(cablesInLoops[i].begin(), cablesInLoops[i].end(),
1871 coalescedCablesInLoops[j].begin(), coalescedCablesInLoops[j].end(),
1872 std::inserter(cablesInBoth, cablesInBoth.begin()));
1874 if (nodesInBoth.size() == nodesInLoops[i].size() && cablesInBoth.size() == cablesInLoops[i].size())
1880 else if (nodesInBoth.size() == coalescedNodesInLoops[j].size() && cablesInBoth.size() == coalescedCablesInLoops[j].size())
1883 coalescedNodesInLoops[j] = nodesInLoops[i];
1884 coalescedCablesInLoops[j] = cablesInLoops[i];
1893 coalescedNodesInLoops.push_back(nodesInLoops[i]);
1894 coalescedCablesInLoops.push_back(cablesInLoops[i]);
1898 for (
size_t i = 0; i < coalescedNodesInLoops.size(); ++i)
1901 "Infinite feedback loop",
1902 "An event is not allowed to travel through the same cable more than once.");
1903 issue.
setHelpPath(
"errors-warnings-and-other-issues.html");
1904 issue.
setNodes(coalescedNodesInLoops[i]);
1905 issue.
setCables(coalescedCablesInLoops[i]);
1924 bool foundIssue =
false;
1928 map<VuoCompilerNode *, set<VuoCompilerNode *> > downstreamNodes;
1929 for (map<Vertex, set<Vertex> >::iterator j = downstreamVertices[trigger].begin(); j != downstreamVertices[trigger].end(); ++j)
1931 Vertex upstreamVertex = j->first;
1932 set<VuoCompilerNode *> downstreamNodesForVertex;
1933 bool isRepeated =
false;
1935 for (set<Vertex>::iterator k = j->second.begin(); k != j->second.end(); ++k)
1937 Vertex downstreamVertex = *k;
1938 if (upstreamVertex.toNode == downstreamVertex.toNode)
1944 downstreamNodesForVertex.insert(downstreamVertex.toNode);
1948 downstreamNodes[upstreamVertex.toNode].insert(downstreamNodesForVertex.begin(), downstreamNodesForVertex.end());
1952 set< pair<VuoCompilerNode *, VuoCompilerNode *> > mutuallyDownstreamNodePairs;
1953 for (map<
VuoCompilerNode *, set<VuoCompilerNode *> >::iterator j = downstreamNodes.begin(); j != downstreamNodes.end(); ++j)
1956 for (set<VuoCompilerNode *>::iterator k = j->second.begin(); k != j->second.end(); ++k)
1959 if (downstreamNodes[downstreamNode].find(upstreamNode) != downstreamNodes[downstreamNode].end() &&
1960 mutuallyDownstreamNodePairs.find( make_pair(downstreamNode, upstreamNode) ) == mutuallyDownstreamNodePairs.end())
1962 mutuallyDownstreamNodePairs.insert( make_pair(upstreamNode, downstreamNode) );
1968 for (set< pair<VuoCompilerNode *, VuoCompilerNode *> >::iterator j = mutuallyDownstreamNodePairs.begin(); j != mutuallyDownstreamNodePairs.end(); ++j)
1973 set<VuoNode *> nodesInLoop;
1974 set<VuoCable *> cablesInLoop;
1975 nodesInLoop.insert(firstNode->
getBase());
1976 nodesInLoop.insert(secondNode->
getBase());
1978 for (set<VuoCompilerNode *>::iterator k = downstreamNodes[firstNode].begin(); k != downstreamNodes[firstNode].end(); ++k)
1981 if (downstreamNodes[otherNode].find(secondNode) != downstreamNodes[otherNode].end())
1982 nodesInLoop.insert(otherNode->
getBase());
1984 for (set<VuoCompilerNode *>::iterator k = downstreamNodes[secondNode].begin(); k != downstreamNodes[secondNode].end(); ++k)
1987 if (downstreamNodes[otherNode].find(firstNode) != downstreamNodes[otherNode].end())
1988 nodesInLoop.insert(otherNode->
getBase());
1991 for (vector<Vertex>::iterator k = vertices[trigger].begin(); k != vertices[trigger].end(); ++k)
1994 if (vertex.fromNode &&
1995 nodesInLoop.find(vertex.fromNode->getBase()) != nodesInLoop.end() &&
1996 nodesInLoop.find(vertex.toNode->getBase()) != nodesInLoop.end())
1998 for (set<VuoCompilerCable *>::iterator m = vertex.cableBundle.begin(); m != vertex.cableBundle.end(); ++m)
1999 cablesInLoop.insert((*m)->getBase());
2004 "Deadlocked feedback loop",
2005 "There's more than one possible path for events to travel through this composition. "
2006 "It's unclear which is the correct one.");
2007 issue.
setHelpPath(
"errors-warnings-and-other-issues.html");
2032 if (node->hasCompiler())
2034 compilerNode = node->getCompiler();
2037 s <<
"{" << compilerNode <<
"," << identifier <<
"},";
2044 for (set<VuoCable *>::iterator i = cables.begin(); i != cables.end(); ++i)
2047 string fromNode = ((*i)->getFromNode() && (*i)->getFromNode()->hasCompiler()) ? (*i)->getFromNode()->getCompiler()->
getIdentifier() :
"";
2048 string fromPort = (*i)->getFromPort() ? (*i)->getFromPort()->getClass()->getName() :
"";
2049 string toNode = ((*i)->getToNode() && (*i)->getToNode()->hasCompiler()) ? (*i)->getToNode()->getCompiler()->
getIdentifier() :
"";
2050 string toPort = (*i)->getToPort() ? (*i)->getToPort()->
getClass()->
getName() :
"";
2051 s <<
"{" << (*i)->getCompiler() <<
"," << fromNode <<
"," << fromPort <<
"," << toNode <<
"," << toPort <<
"},";
2058 for (vector<VuoPublishedPort *>::iterator i = publishedInputPorts.begin(); i != publishedInputPorts.end(); ++i)
2059 s <<
"{" << (*i)->getCompiler() <<
"," << (*i)->getClass()->getName() <<
"},";
2063 for (vector<VuoPublishedPort *>::iterator i = publishedOutputPorts.begin(); i != publishedOutputPorts.end(); ++i)
2064 s <<
"{" << (*i)->getCompiler() <<
"," << (*i)->getClass()->getName() <<
"},";
2070 if (manuallyFirableInputPort)
2090 return "ManuallyFirableTrigger";
2098 this->fromNode = NULL;
2099 this->fromTrigger = fromTrigger;
2100 this->toNode = toNode;
2108 this->fromTrigger = NULL;
2109 this->fromNode = fromNode;
2110 this->toNode = toNode;
2116 VuoCompilerGraph::Vertex::Vertex(
void)
2118 this->fromNode = NULL;
2119 this->fromTrigger = NULL;
2120 this->toNode = NULL;
2126 VuoCompilerGraph::Edge::Edge(
const VuoCompilerGraph::Vertex &fromVertex,
const VuoCompilerGraph::Vertex &toVertex)
2127 : fromVertex(fromVertex), toVertex(toVertex)
2134 VuoCompilerGraph::Edge::Edge(
void)
2141 bool operator==(
const VuoCompilerGraph::Vertex &lhs,
const VuoCompilerGraph::Vertex &rhs)
2143 return (lhs.fromTrigger == rhs.fromTrigger && lhs.fromNode == rhs.fromNode && lhs.toNode == rhs.toNode);
2149 bool operator!=(
const VuoCompilerGraph::Vertex &lhs,
const VuoCompilerGraph::Vertex &rhs)
2151 return ! (lhs == rhs);
2157 bool operator<(
const VuoCompilerGraph::Vertex &lhs,
const VuoCompilerGraph::Vertex &rhs)
2159 return (lhs.fromTrigger != rhs.fromTrigger ?
2160 lhs.fromTrigger < rhs.fromTrigger :
2161 (lhs.fromNode != rhs.fromNode ?
2162 lhs.fromNode < rhs.fromNode :
2163 lhs.toNode < rhs.toNode));
2169 bool operator<(
const VuoCompilerGraph::Edge &lhs,
const VuoCompilerGraph::Edge &rhs)
2171 return (lhs.fromVertex != rhs.fromVertex ?
2172 lhs.fromVertex < rhs.fromVertex :
2173 lhs.toVertex < rhs.toVertex);
2179 string VuoCompilerGraph::Vertex::toString(
void)
const
2183 fromTrigger->getBase()->getClass()->getName()) +
2190 string VuoCompilerGraph::Edge::toString(
void)
const
2192 return fromVertex.toString() +
" -> " + toVertex.toString();