private TarjanData GetTarjan(IPipelineStage stage)
 {
     if (!Tarjan.TryGetValue(stage, out var tarjan))
     {
         tarjan = new TarjanData(stage);
         Tarjan.Add(stage, tarjan);
     }
     return(tarjan);
 }
        private void StrongConnect(Stack <TarjanData> s, TarjanData v, ref int index, List <List <IPipelineStage> > output)
        {
            v.Index   = index;
            v.LowLink = index++;
            s.Push(v);
            v.OnStack = true;
            foreach (var n in GetDependentStages(v.Stage))
            {
                if (!n.TryGetTarget(out var dependent))
                {
                    continue;
                }

                var w = GetTarjan(dependent);
                if (w.Index == TarjanData.Undefined)
                {
                    StrongConnect(s, w, ref index, output);
                    v.LowLink = Math.Min(v.LowLink, w.LowLink);
                }
                else if (w.OnStack)
                {
                    v.LowLink = Math.Min(v.LowLink, w.Index);
                }
            }

            if (v.LowLink == v.Index)
            {
                var        ssc = new List <IPipelineStage>();
                TarjanData w;
                do
                {
                    w         = s.Pop();
                    w.OnStack = false;
                    ssc.Add(w.Stage);
                } while (w != v);

                output.Add(ssc);
            }
        }