public void MultiToSingle() { // Multi | Single // S -> Process -> Sync -> Process -> End List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), sync = new DependentNode(1, SyncNode.TypeName), pro1 = new DependentNode(2, "pro"), pro2 = new DependentNode(3, "pro"), end = new DependentNode(4, "end"); nodes.Add(start); nodes.Add(pro1); nodes.Add(sync); nodes.Add(pro2); nodes.Add(end); TestHelpers.MatchSlots(start, pro1, 0, 0); TestHelpers.MatchSlots(pro1, sync, 0, 0); TestHelpers.MatchSlots(sync, pro2, 0, 0); TestHelpers.MatchSlots(pro2, end, 0, 0); DataStore staticData = new DataStore(true); SpecialNodeData data = SpecialNodeSearch.CheckForSpecialNodes(TestHelpers.ConvertToDictionary(nodes), staticData); Assert.AreEqual(1, data.SyncInformation.SyncNodes.Length); Assert.AreEqual(0, data.SyncInformation.NodeGroups[0].Dependents.Length); Assert.AreEqual(1, data.SyncInformation.NodeGroups[1].CalledBy); }
private void FindLoopEnd(DependentNode node, ref List <int> done) { if (done.Contains(node.Id)) { return; } foreach (NodeSlot slot in node.Dependencies) { DependentNode testNode = dependencyGraph[slot.NodeId]; if (done.Contains(testNode.Id)) { continue; } if (testNode.Type == LoopEnd.TypeName) { FindLoopPairs(testNode, ref done); } else { FindLoopEnd(testNode, ref done); } } done.Add(node.Id); }
public void SharedNestedLoopStart() { // ᴧ >> >> >> v // S -> LoopStart -> LoopEnd -> LoopEnd -> End // 0 1 2 4 3 List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), loopStart = new DependentNode(1, LoopStart.TypeName), loopEnd1 = new DependentNode(2, LoopEnd.TypeName), loopEnd2 = new DependentNode(3, LoopEnd.TypeName), end = new DependentNode(4, "end"); nodes.Add(start); nodes.Add(loopStart); nodes.Add(loopEnd1); nodes.Add(loopEnd2); nodes.Add(end); TestHelpers.MatchSlots(start, loopStart, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd1, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd1, 2, 2); TestHelpers.MatchSlots(loopStart, loopEnd2, 0, 0); TestHelpers.MatchSlots(loopEnd1, loopEnd2, 0, 2); TestHelpers.MatchSlots(loopEnd2, end, 0, 0); Assert.Throws <SlotLimitExceeded>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); }
/// <summary> /// Looks at the dependencies of a node and checks if any match the given types /// </summary> /// <param name="node">search node</param> /// <param name="matchedNode">id of the node that was of the given types, -1 if no match is found</param> /// <param name="tested">list of ids that have been checked</param> /// <param name="types">the node types that will be looked for</param> /// <returns>true if the node has a dependency of 'types'</returns> private bool CheckDependenciesFor(DependentNode node, out int matchedNode, List <int> tested, params string[] types) { if (tested.Contains(node.Id)) { matchedNode = -1; return(false); } foreach (NodeSlot slot in node.Dependencies) { DependentNode testNode = dependencyGraph[slot.NodeId]; for (int i = 0; i < types.Length; i++) { if (testNode.Type == types[i] && !tested.Contains(testNode.Id)) { matchedNode = testNode.Id; return(true); } } if (CheckDependenciesFor(testNode, out matchedNode, tested, types)) { return(true); } } tested.Add(node.Id); matchedNode = -1; return(false); }
public List <LoopPair> FindLoops() { List <int> done = new List <int>(); DependentNode[] nodes = dependencyGraph.Values.ToArray(); //sanity check for existing loops bool loopEnds = false; foreach (DependentNode node in nodes) { if (node.Type == LoopEnd.TypeName) { loopEnds = true; break; } } if (!loopEnds) { return(new List <LoopPair>()); } //find end points for (int i = nodes.Length - 1; i >= 0; i--) { DependentNode node = nodes[i]; if (PluginStore.isOutputPlugin(node.Type)) { FindLoopEnd(node, ref done); } } return(loopPairs); }
private bool NodeDependentOn(int search, int target, ref List <int> checkedNodes) { DependentNode node = dependencyGraph[search]; for (int i = 0; i < node.Dependencies.Length; i++) { int nodeId = node.Dependencies[i].NodeId; if (checkedNodes.Contains(nodeId)) { continue; } if (nodeId == target && NodeDependentOn(nodeId, target, ref checkedNodes)) { return(true); } if (NodeDependentOn(nodeId, target, ref checkedNodes)) { return(true); } checkedNodes.Add(nodeId); } return(false); }
public void CodependentLoop() { // ᴧ >> >> >> v // S -> LoopStart -> LoopStart -> LoopEnd -> LoopEnd -> End // v >> >> >> ᴧ List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), loopStart1 = new DependentNode(1, LoopStart.TypeName), loopEnd1 = new DependentNode(2, LoopEnd.TypeName), loopStart2 = new DependentNode(3, LoopStart.TypeName), loopEnd2 = new DependentNode(4, LoopEnd.TypeName), process = new DependentNode(6, "pro"), end = new DependentNode(5, "end"); nodes.Add(start); nodes.Add(loopStart1); nodes.Add(loopStart2); nodes.Add(loopEnd1); nodes.Add(loopEnd2); nodes.Add(process); nodes.Add(end); TestHelpers.MatchSlots(start, loopStart1, 0, 0); TestHelpers.MatchSlots(loopStart1, loopEnd1, 0, 0); TestHelpers.MatchSlots(loopStart1, loopStart2, 1, 2); TestHelpers.MatchSlots(loopStart2, process, 2, 0); TestHelpers.MatchSlots(loopStart2, loopEnd2, 0, 0); TestHelpers.MatchSlots(process, loopEnd1, 0, 2); TestHelpers.MatchSlots(loopEnd1, loopEnd2, 0, 2); TestHelpers.MatchSlots(loopEnd2, end, 0, 0); Assert.Throws <CoDependentLoopException>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); }
public void ImbalancedLoopLinkException() { List <DependentNode> nodes = new List <DependentNode>(); { // start node DependentNode dep = new DependentNode(0, "start"); dep.AddDependent(1, 0, 0); nodes.Add(dep); } { // loop start DependentNode dep = new DependentNode(1, LoopStart.TypeName); dep.AddDependency(0, 0, 0); //dep.AddDependent(2, 0, 0); dep.AddDependent(2, 2, 0); nodes.Add(dep); } { // first loop end DependentNode dep = new DependentNode(2, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 0, 0); nodes.Add(dep); } { // end node DependentNode dep = new DependentNode(3, "end"); dep.AddDependency(2, 0, 0); nodes.Add(dep); } MissingLinkException exception = Assert.Throws <MissingLinkException>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); Assert.AreEqual("No link for loop start specified", exception.Message); }
public void SimpleExtendedLoop() { // S -> LoopStart -> LoopEnd -> Process -> End List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), loopStart = new DependentNode(1, LoopStart.TypeName), loopEnd = new DependentNode(2, LoopEnd.TypeName), process = new DependentNode(3, "pro"), end = new DependentNode(4, "end"); nodes.Add(start); nodes.Add(loopStart); nodes.Add(loopEnd); nodes.Add(process); nodes.Add(end); TestHelpers.MatchSlots(start, loopStart, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd, 1, 2); TestHelpers.MatchSlots(loopEnd, process, 0, 0); TestHelpers.MatchSlots(process, end, 0, 0); List <LoopPair> loops = new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops(); Assert.AreEqual(1, loops.Count, "incorrect amount of loops detected"); Assert.AreEqual(0, loops[0].Depth); }
public void NoSync() { // Multi // S -> Process -> Process -> End List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), pro1 = new DependentNode(2, "pro"), pro2 = new DependentNode(3, "pro"), end = new DependentNode(4, "end"); nodes.Add(start); nodes.Add(pro1); nodes.Add(pro2); nodes.Add(end); TestHelpers.MatchSlots(start, pro1, 0, 0); TestHelpers.MatchSlots(pro1, pro2, 0, 0); TestHelpers.MatchSlots(pro2, end, 0, 0); DataStore staticData = new DataStore(true); SpecialNodeData data = SpecialNodeSearch.CheckForSpecialNodes(TestHelpers.ConvertToDictionary(nodes), staticData); Assert.AreEqual(0, data.SyncInformation.SyncNodes.Length, "There should not be any sync blocks in this test"); Assert.AreEqual(null, data.SyncInformation.NodeGroups); }
private bool Insert(Dependent update) { lock (this) { bool first = _firstDependent == null; _firstDependent = new DependentNode { Dependent = new WeakReference(update), Next = _firstDependent }; return(first); } }
private bool Contains(Dependent update) { lock (this) { for (DependentNode current = _firstDependent; current != null; current = current.Next) { if (current.Dependent.Target == update) { return(true); } } return(false); } }
public void MiddleExitLoops() { // End // ᴧ // S -> LoopStart -> LoopEnd -> End List <DependentNode> nodes = new List <DependentNode>(); { // start node DependentNode dep = new DependentNode(0, "start"); dep.AddDependent(1, 0, 0); nodes.Add(dep); } { // loop start DependentNode dep = new DependentNode(1, LoopStart.TypeName); dep.AddDependency(0, 0, 0); dep.AddDependent(2, 0, 0); dep.AddDependent(2, 2, 1); dep.AddDependent(4, 1, 0); nodes.Add(dep); } { // condition for end loop DependentNode dep = new DependentNode(5, "condition"); dep.AddDependent(2, 1, 0); nodes.Add(dep); } { // middle end DependentNode dep = new DependentNode(4, "end"); dep.AddDependency(1, 1, 0); nodes.Add(dep); } { // loop end DependentNode dep = new DependentNode(2, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(5, 0, 1); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 0, 0); nodes.Add(dep); } { // end node DependentNode dep = new DependentNode(3, "end"); dep.AddDependency(2, 0, 0); nodes.Add(dep); } List <LoopPair> loops = new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops(); Assert.AreEqual(1, loops.Count, "incorrect amount of loops detected"); Assert.AreEqual(0, loops[0].Depth); }
public SyncNode(DependentNode nodeId, DataStore staticData) { NodeId = nodeId.Id; graphNode = nodeId; this.staticData = staticData; //build dictionary foreach (NodeSlot node in nodeId.Dependencies) { if (data.ContainsKey(node.NodeId)) { continue; } data.Add(node.NodeId, new List <byte[]>()); } }
public void NodeDependencyOrder(int[] slots) { DependentNode node = new DependentNode(0, "node"); foreach (int slot in slots) { node.AddDependency(slot, 0, slot); } int lastSlot = -1; foreach (NodeSlot dependency in node.Dependencies) { Assert.Greater(dependency.NodeId, lastSlot); lastSlot = dependency.SlotPos; } }
private Dependent First() { lock (this) { while (_firstDependent != null) { Dependent dependent = (Dependent)_firstDependent.Dependent.Target; if (dependent != null) { return(dependent); } else { _firstDependent = _firstDependent.Next; } } return(null); } }
public void SimpleSlotDependencies() { List <DependentNode> nodes = new List <DependentNode>(); DependentNode a = new DependentNode(0, "a"), b = new DependentNode(1, "b"), c = new DependentNode(2, "c"); nodes.Add(a); nodes.Add(b); nodes.Add(c); TestHelpers.MatchSlots(b, a, 0, 0); TestHelpers.MatchSlots(b, c, 1, 0); NodeSlot resultSlot = ExecutionHelper.FindFirstNodeSlotInDependents(b, TestHelpers.ConvertToDictionary(nodes), 0); Assert.AreEqual(a.Id, resultSlot.NodeId); }
public void MultiToSingleToMulti() { // Multi | Single | Multi // S -> Process -> Sync -> Process -> Sync -> Process -> End // v-------------------------------------ᴧ List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), sync = new DependentNode(1, SyncNode.TypeName), sync2 = new DependentNode(6, SyncNode.TypeName), pro1 = new DependentNode(2, "pro"), pro2 = new DependentNode(3, "pro"), pro3 = new DependentNode(5, "pro"), end = new DependentNode(4, "end"); nodes.Add(start); nodes.Add(pro1); nodes.Add(sync); nodes.Add(sync2); nodes.Add(pro2); nodes.Add(pro3); nodes.Add(end); TestHelpers.MatchSlots(start, pro1, 0, 0); TestHelpers.MatchSlots(pro1, sync, 0, 0); TestHelpers.MatchSlots(pro1, pro3, 1, 1); TestHelpers.MatchSlots(sync, pro2, 0, 0); TestHelpers.MatchSlots(pro2, sync2, 0, 0); TestHelpers.MatchSlots(sync2, pro3, 0, 0); TestHelpers.MatchSlots(pro3, end, 0, 0); DataStore staticData = new DataStore(true); SpecialNodeData data = SpecialNodeSearch.CheckForSpecialNodes(TestHelpers.ConvertToDictionary(nodes), staticData); Assert.AreEqual(2, data.SyncInformation.SyncNodes.Length); Assert.AreEqual(3, data.SyncInformation.NodeGroups.Count); Assert.AreEqual(sync.Id, data.SyncInformation.NodeGroups[1].CalledBy); Assert.AreEqual(sync2.Id, data.SyncInformation.NodeGroups[2].CalledBy); Assert.IsTrue(data.SyncInformation.NodeGroups[0].Dependents.Contains(pro3.Id)); }
public void NoLoop() { // S -> End List <DependentNode> nodes = new List <DependentNode>(); { // start node DependentNode dep = new DependentNode(0, "start"); dep.AddDependent(3, 0, 0); nodes.Add(dep); } { // end node DependentNode dep = new DependentNode(3, "end"); dep.AddDependency(0, 0, 0); nodes.Add(dep); } List <LoopPair> loops = new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops(); Assert.AreEqual(0, loops.Count, "incorrect amount of loops detected"); }
public void SyncGeneratorInputException() { // S -> Sync -> End //Gen-> List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), gen = new DependentNode(1, "gen"), sync2 = new DependentNode(6, SyncNode.TypeName); nodes.Add(start); nodes.Add(gen); nodes.Add(sync2); TestHelpers.MatchSlots(start, sync2, 0, 0); TestHelpers.MatchSlots(gen, sync2, 0, 1); DataStore staticData = new DataStore(true); Assert.Throws <InvalidConnectionException>(() => SpecialNodeSearch.CheckForSpecialNodes(TestHelpers.ConvertToDictionary(nodes), staticData)); }
public void InvalidLoopStartConnection() { List <DependentNode> nodes = new List <DependentNode>(); { // start node DependentNode dep = new DependentNode(0, "start"); dep.AddDependent(1, 0, 0); nodes.Add(dep); } { // loop start DependentNode dep = new DependentNode(1, LoopStart.TypeName); dep.AddDependency(0, 0, 0); dep.AddDependent(2, 0, 0); dep.AddDependent(3, 0, 0); //Can't connect to non Loop End node dep.AddDependent(2, 2, 1); nodes.Add(dep); } { // condition for end loop DependentNode dep = new DependentNode(5, "condition"); dep.AddDependent(2, 1, 0); nodes.Add(dep); } { // loop end DependentNode dep = new DependentNode(2, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(5, 0, 1); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 0, 0); nodes.Add(dep); } { // end node DependentNode dep = new DependentNode(3, "end"); dep.AddDependency(1, 0, 1); dep.AddDependency(2, 0, 0); nodes.Add(dep); } InvalidNodeException exception = Assert.Throws <InvalidNodeException>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); Assert.AreEqual("Loop Start Link (slot 0) cannot link to anything but a Loop End", exception.Message); }
private bool Delete(Dependent dependent) { lock (this) { int count = 0; DependentNode prior = null; for (DependentNode current = _firstDependent; current != null; current = current.Next) { object target = current.Dependent.Target; if (target == null || target == dependent) { if (target == null) { System.Diagnostics.Debug.WriteLine(String.Format("Dead reference {0}", _referenceCount++)); } if (target == dependent) { ++count; } if (prior == null) { _firstDependent = current.Next; } else { prior.Next = current.Next; } } else { prior = current; } } if (count != 1) { Debug.Assert(false, String.Format("Expected 1 dependent, found {0}.", count)); } return(_firstDependent == null); } }
public void NestedLoop2() { // S -> LoopStart -> LoopStart -> Process -> LoopEnd -> LoopEnd -> End List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), outerLoopStart = new DependentNode(1, LoopStart.TypeName), innerLoopStart = new DependentNode(2, LoopStart.TypeName), process = new DependentNode(3, ""), innerLoopEnd = new DependentNode(4, LoopEnd.TypeName), outerLoopEnd = new DependentNode(5, LoopEnd.TypeName), end = new DependentNode(6, "end"); nodes.Add(start); nodes.Add(outerLoopEnd); nodes.Add(innerLoopEnd); nodes.Add(innerLoopStart); nodes.Add(outerLoopStart); nodes.Add(process); nodes.Add(end); TestHelpers.MatchSlots(start, outerLoopStart, 0, 0); TestHelpers.MatchSlots(outerLoopStart, outerLoopEnd, 0, 0); TestHelpers.MatchSlots(outerLoopStart, innerLoopStart, 2, 2); TestHelpers.MatchSlots(innerLoopStart, innerLoopEnd, 0, 0); TestHelpers.MatchSlots(innerLoopStart, process, 2, 0); TestHelpers.MatchSlots(process, innerLoopEnd, 0, 2); TestHelpers.MatchSlots(innerLoopEnd, outerLoopEnd, 0, 2); TestHelpers.MatchSlots(outerLoopEnd, end, 0, 0); List <LoopPair> loops = new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops(); Assert.AreEqual(2, loops.Count, "incorrect amount of loops detected"); Assert.AreEqual(1, loops[0].Depth); Assert.AreEqual(0, loops[1].Depth); Assert.AreNotSame(loops[0].Id, loops[1].Id); Assert.AreNotSame(loops[0].End.NodeId, loops[1].End.NodeId); }
public void SplitLoops() { // -> LoopEnd -> End // S -> LoopStart // -> LoopEnd -> End List <DependentNode> nodes = new List <DependentNode>(); DependentNode start = new DependentNode(0, "start"), loopStart = new DependentNode(1, LoopStart.TypeName), loopEnd1 = new DependentNode(2, LoopEnd.TypeName), loopEnd2 = new DependentNode(3, LoopEnd.TypeName), end1 = new DependentNode(4, "end"), end2 = new DependentNode(5, "end"); nodes.Add(start); nodes.Add(loopStart); nodes.Add(loopEnd1); nodes.Add(loopEnd2); nodes.Add(end1); nodes.Add(end2); TestHelpers.MatchSlots(start, loopStart, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd1, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd1, 1, 2); TestHelpers.MatchSlots(loopEnd1, end1, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd2, 0, 0); TestHelpers.MatchSlots(loopStart, loopEnd2, 1, 2); TestHelpers.MatchSlots(loopEnd2, end2, 0, 0); Assert.Throws <SlotLimitExceeded>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); /*List<LoopPair> loops = pipe.getLoops(); * Assert.AreEqual(2, loops.Count, "incorrect amount of loops detected"); * Assert.AreEqual(0, loops[0].Depth); * Assert.AreEqual(0, loops[1].Depth); * Assert.AreNotSame(loops[0].Id, loops[1].Id);*/ }
public void PartialLoopLinksException() { List <DependentNode> nodes = new List <DependentNode>(); { // start node DependentNode dep = new DependentNode(0, "start"); dep.AddDependent(1, 0, 0); nodes.Add(dep); } { // loop start DependentNode dep = new DependentNode(1, LoopStart.TypeName); dep.AddDependency(0, 0, 0); dep.AddDependent(2, 0, 0); // Loop start only linked to first loop end nodes.Add(dep); } { // first loop end DependentNode dep = new DependentNode(2, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 0, 0); nodes.Add(dep); } { // random loop end DependentNode dep = new DependentNode(4, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 1, 0); nodes.Add(dep); } { // end node DependentNode dep = new DependentNode(3, "end"); dep.AddDependency(2, 0, 0); dep.AddDependency(4, 0, 1); nodes.Add(dep); } Assert.Throws <MissingLinkException>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); }
public void MultiSlotDependents() { List <DependentNode> nodes = new List <DependentNode>(); DependentNode a = new DependentNode(0, "a"), b = new DependentNode(1, "b"), c = new DependentNode(2, "c"), d = new DependentNode(3, "d"); nodes.Add(a); nodes.Add(b); nodes.Add(c); nodes.Add(d); TestHelpers.MatchSlots(a, b, 0, 0); TestHelpers.MatchSlots(b, c, 1, 0); TestHelpers.MatchSlots(b, d, 1, 0); NodeSlot[] resultSlots = ExecutionHelper.FindAllNodeSlotsInDependents(b, TestHelpers.ConvertToDictionary(nodes), 1); Assert.AreEqual(2, resultSlots.Length); Assert.AreEqual(c.Id, resultSlots[0].NodeId); Assert.AreEqual(d.Id, resultSlots[1].NodeId); }
private List <NodeSlot> FindContainingNodeIds(int loopStart, int loopEnd) { DependentNode start = dependencyGraph[loopStart]; List <NodeSlot> ids = new List <NodeSlot>(); for (int i = 0; i < start.Dependents.Length; i++) { if (start.Dependents[i].NodeId == loopEnd) { continue; } List <NodeSlot> id = new List <NodeSlot>(); id.Add(start.Dependents[i]); Tuple <bool, List <NodeSlot> > traversed = TraverseNodeDependents(id, start.Dependents[i].NodeId, loopEnd); if (traversed.Item1) { ids.AddRange(traversed.Item2); } } return(ids); }
private bool Delete(Dependent dependent) { lock (this) { int count = 0; DependentNode prior = null; for (DependentNode current = _firstDependent; current != null; current = current.Next) { object target = current.Dependent.Target; if (target == null || target == dependent) { if (target == null) System.Diagnostics.Debug.WriteLine(String.Format("Dead reference {0}", _referenceCount++)); if (target == dependent) ++count; if (prior == null) _firstDependent = current.Next; else prior.Next = current.Next; } else prior = current; } if (count != 1) Debug.Assert(false, String.Format("Expected 1 dependent, found {0}.", count)); return _firstDependent == null; } }
private Dependent First() { lock (this) { while (_firstDependent != null) { Dependent dependent = (Dependent)_firstDependent.Dependent.Target; if (dependent != null) return dependent; else _firstDependent = _firstDependent.Next; } return null; } }
private bool Insert(Dependent update) { lock (this) { bool first = _firstDependent == null; _firstDependent = new DependentNode { Dependent = new WeakReference(update), Next = _firstDependent }; return first; } }
private void FindLoopPairs(DependentNode loopEnd, ref List <int> foundEnds, int depth = 0) { LoopPair instance = new LoopPair(); instance.Id = loopIdCount++; if (loopEnd.Type == LoopEnd.TypeName) { instance.End = new LoopEnd(loopEnd, instance); instance.Depth = depth; int startNode = ExecutionHelper.FindFirstNodeSlotInDependencies(loopEnd, dependencyGraph, 0).NodeId; if (startNode == -1) { throw new MissingLinkException("No link for loop start specified"); } DependentNode loopStart = dependencyGraph[startNode]; //try to keep one instance per unique loop start node Id if (loopStarts.ContainsKey(startNode)) { instance.Start = loopStarts[startNode]; } else { instance.Start = new LoopStart(loopStart); loopStarts.Add(startNode, instance.Start); } //ensure that only the start and end nodes are linked if (loopStart.Dependents.Where((testSlot, b) => { bool incorrectType = dependencyGraph[testSlot.NodeId].Type != LoopEnd.TypeName; foreach (NodeSlot slot in dependencyGraph[testSlot.NodeId].Dependencies) { if (slot.NodeId == loopStart.Id && slot.SlotPos == 0) { if (incorrectType) { return(true); } } } return(false); }).Any()) { throw new InvalidNodeException("Loop Start Link (slot 0) cannot link to anything but a Loop End"); } //find out how many loops the "LoopStart" node is directly responsible for int loopCount; { List <int> matched = new List <int>(); loopCount = loopStart.Dependents.Where((testSlot, b) => { if (matched.Contains(testSlot.NodeId)) { return(false); } foreach (NodeSlot slot in dependencyGraph[testSlot.NodeId].Dependencies) { if (slot.NodeId == loopStart.Id && slot.SlotPos == 0) { matched.Add(testSlot.NodeId); return(true); } } return(false); }).Count(); } if (loopCount > 1) { throw new SlotLimitExceeded("Loop Start may only have one loop end, use multiple loop starts for nesting or branching"); #region //multiple nodes linked so there must be nested loops sharing this start position /*int[] ids = new int[loopCount]; * for (int i = 0, c = 0; i < loopStart.Dependents.Length; i++) * if (loopStart.Dependents[i].SlotPos == 0) * ids[c++] = loopStart.Dependents[i].NodeId; * * //check if co dependent nodes exist * List<int> dependencies = new List<int>(); * for (int a = 0; a < ids.Length; a++) * { * for (int b = 0; b < ids.Length; b++) * { * if (a == b) continue; * * bool aTob = NodeDependentOn(ids[a], ids[b]), * bToa = NodeDependentOn(ids[b], ids[a]); * * if (aTob && bToa) throw new CoDependentLoopException * ("Node " + ids[a] + " and " + ids[b] + "Are dependent on each other and can't loop!"); * * if (aTob && !dependencies.Contains(a)) dependencies.Add(ids[a]); * } * } * * //check non dependent nodes for internal loops * foreach (int id in ids) * { * if (dependencies.Contains(id)) continue; * * LoopPair subPair = new LoopPair(); * subPair.Id = loopIdCount++; * subPair.Depth = depth; * subPair.End = new LoopEnd(dependencyGraph[id], subPair); * if (loopStarts.ContainsKey(loopEnd.Dependencies[0].NodeId)) * subPair.Start = loopStarts[loopEnd.Dependencies[0].NodeId]; * else * { * instance.Start = new LoopStart(dependencyGraph[loopEnd.Dependencies[0].NodeId]); * loopStarts.Add(loopEnd.Dependencies[0].NodeId, subPair.Start); * } * * int foundEnd; * if (ContainsLoop(instance, out foundEnd)) * //contains internal loop * FindLoopPairs(dependencyGraph[foundEnd], ref foundEnds, subPair.Depth + 1); * * foundEnds.Add(subPair.End.NodeId); * subPair.Start.AddLoopPair(ref subPair); * loopPairs.Add(subPair); * } * * //go back and handle the nodes which are dependent on each other * if (dependencies.Count > 1) * { * throw new NotImplementedException(); * //todo * }*/ #endregion } else { NodeSlot startLink = ExecutionHelper.FindFirstNodeSlotInDependents(loopStart, dependencyGraph, 0); if (startLink.NodeId == -1) { throw new MissingLinkException("No link for loop start specified"); } if (startLink.NodeId != loopEnd.Id) { throw new MissingLinkException(StartEndIdMismatch); } int foundEnd; //contains internal loop? if (ContainsLoop(instance, out foundEnd)) { FindLoopPairs(dependencyGraph[foundEnd], ref foundEnds, instance.Depth + 1); } instance.ContainedNodes = FindContainingNodeIds(instance.Start.NodeId, instance.End.NodeId); int start = 0, end = 0; foreach (NodeSlot nodes in instance.ContainedNodes) { if (dependencyGraph[nodes.NodeId].Type == LoopStart.TypeName) { start += 1; } else if (dependencyGraph[nodes.NodeId].Type == LoopEnd.TypeName) { end += 1; } } if (start != end) { throw new CoDependentLoopException(); } foundEnds.Add(instance.End.NodeId); instance.Start.AddLoopPair(ref instance); loopPairs.Add(instance); } } else if (loopEnd.Type == LoopStart.TypeName) { //abort as you are in the middle of a loop rather than at the end if (instance.End == null) { return; } } }
public static void MatchSlots(DependentNode a, DependentNode b, int aSlot, int bSlot) { a.AddDependent(b.Id, bSlot, aSlot); b.AddDependency(a.Id, aSlot, bSlot); }
public void DuelLoops() { // -> LoopEnd -> // S -> LoopStart End // -> LoopEnd -> List <DependentNode> nodes = new List <DependentNode>(); { // start node DependentNode dep = new DependentNode(0, "start"); dep.AddDependent(1, 0, 0); nodes.Add(dep); } { // loop start DependentNode dep = new DependentNode(1, LoopStart.TypeName); dep.AddDependency(0, 0, 0); dep.AddDependent(2, 0, 0); dep.AddDependent(2, 2, 1); dep.AddDependent(4, 0, 0); dep.AddDependent(4, 2, 1); nodes.Add(dep); } { // condition for first end loop DependentNode dep = new DependentNode(5, "condition"); dep.AddDependent(2, 1, 0); nodes.Add(dep); } { // first loop end DependentNode dep = new DependentNode(2, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(5, 0, 1); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 0, 0); nodes.Add(dep); } { // condition for second end loop DependentNode dep = new DependentNode(6, "condition"); dep.AddDependent(4, 1, 0); nodes.Add(dep); } { // second loop end DependentNode dep = new DependentNode(4, LoopEnd.TypeName); dep.AddDependency(1, 0, 0); dep.AddDependency(6, 0, 1); dep.AddDependency(1, 1, 2); dep.AddDependent(3, 1, 0); nodes.Add(dep); } { // end node DependentNode dep = new DependentNode(3, "end"); dep.AddDependency(2, 0, 0); dep.AddDependency(4, 0, 1); nodes.Add(dep); } Assert.Throws <SlotLimitExceeded>(() => new LoopDetector(TestHelpers.ConvertToDictionary(nodes)).FindLoops()); /*List<LoopPair> loops = pipe.getLoops(); * Assert.AreEqual(2, loops.Count, "incorrect amount of loops detected"); * Assert.AreEqual(0, loops[0].Depth); * Assert.AreEqual(0, loops[1].Depth); * Assert.AreNotSame(loops[1].Id, loops[1].Id);*/ }