예제 #1
0
            public TestAtomicModule(int inportCount, int outportCount)
            {
                var inports  = Enumerable.Range(0, inportCount).Select(i => new Inlet <object>(".in" + i)).ToImmutableArray <Inlet>();
                var outports = Enumerable.Range(0, outportCount).Select(i => new Outlet <object>(".out" + i)).ToImmutableArray <Outlet>();

                Shape = new AmorphousShape(inports, outports);
            }
예제 #2
0
        /// <summary>
        /// Transform a set of GraphStageModules into a single GraphModule. This is done
        /// by performing a traversal of all their Inlets, sorting them into those without
        /// internal connections(the exposed inlets) and those with internal connections
        /// (where the corresponding Outlet is recorded in a map so that it will be wired
        /// to the same slot number in the GraphAssembly). Then all Outlets are traversed,
        /// completing internal connections using the aforementioned maps and appending
        /// the others to the list of exposed Outlets.
        /// </summary>
        private static GraphModule FuseGroup(BuildStructuralInfo info, ISet <IModule> group)
        {
            var stages = new IGraphStageWithMaterializedValue <Shape, object> [group.Count];
            var materializedValueIds = new IModule[group.Count];
            var attributes           = new Attributes[group.Count];

            /*
             * The overall GraphAssembly arrays are constructed in three parts:
             * - 1) exposed inputs (ins)
             * - 2) connections (ins and outs)
             * - 3) exposed outputs (outs)
             */
            var insB1       = new List <Inlet>();
            var insB2       = new List <Inlet>();
            var outsB3      = new List <Outlet>();
            var inOwnersB1  = new List <int>();
            var inOwnersB2  = new List <int>();
            var outOwnersB3 = new List <int>();

            // for the shape of the GraphModule
            var inlets  = ImmutableArray.CreateBuilder <Inlet>(2);
            var outlets = ImmutableArray.CreateBuilder <Outlet>(2);

            // connection slots are allocated from the inputs side, outs find their place by this map
            var outConns = new Dictionary <OutPort, int>();

            /*
             * First traverse all Inlets and sort them into exposed and internal,
             * taking note of their partner Outlets where appropriate.
             */
            var pos        = 0;
            var enumerator = group.GetEnumerator();
            var ups        = info.Upstreams;
            var downs      = info.Downstreams;
            var outGroup   = info.OutGroups;

            while (enumerator.MoveNext())
            {
                CopiedModule     copy;
                GraphStageModule graphStageModule;
                if ((copy = enumerator.Current as CopiedModule) != null && (graphStageModule = copy.CopyOf as GraphStageModule) != null)
                {
                    stages[pos] = graphStageModule.Stage;
                    materializedValueIds[pos] = copy;
                    attributes[pos]           = copy.Attributes.And(graphStageModule.Attributes);

                    var copyInlets     = copy.Shape.Inlets.GetEnumerator();
                    var originalInlets = graphStageModule.Shape.Inlets.GetEnumerator();
                    while (copyInlets.MoveNext() && originalInlets.MoveNext())
                    {
                        var copyInlet     = copyInlets.Current;
                        var originalInlet = originalInlets.Current;
                        var isInternal    = ups.TryGetValue(copyInlet, out var outport) &&
                                            outGroup.TryGetValue(outport, out var g) &&
                                            g == group;
                        if (isInternal)
                        {
                            ups.Remove(copyInlet);

                            downs.Remove(outport);
                            outConns[outport] = insB2.Count;
                            insB2.Add(originalInlet);
                            inOwnersB2.Add(pos);
                        }
                        else
                        {
                            insB1.Add(originalInlet);
                            inOwnersB1.Add(pos);
                            inlets.Add(copyInlet);
                        }
                    }
                    pos++;
                }
                else
                {
                    throw new ArgumentException("unexpected module structure");
                }
            }

            var outsB2      = new Outlet[insB2.Count];
            var outOwnersB2 = new int[insB2.Count];

            /*
             * Then traverse all Outlets and complete connections.
             */
            pos        = 0;
            enumerator = group.GetEnumerator();
            while (enumerator.MoveNext())
            {
                CopiedModule     copy;
                GraphStageModule graphStageModule;
                if ((copy = enumerator.Current as CopiedModule) != null && (graphStageModule = copy.CopyOf as GraphStageModule) != null)
                {
                    var copyOutlets     = copy.Shape.Outlets.GetEnumerator();
                    var originalOutlets = graphStageModule.Shape.Outlets.GetEnumerator();
                    while (copyOutlets.MoveNext() && originalOutlets.MoveNext())
                    {
                        var copyOutlet     = copyOutlets.Current;
                        var originalOutlet = originalOutlets.Current;
                        if (outConns.TryGetValue(copyOutlet, out int idx))
                        {
                            outConns.Remove(copyOutlet);
                            outsB2[idx]      = originalOutlet;
                            outOwnersB2[idx] = pos;
                        }
                        else
                        {
                            outsB3.Add(originalOutlet);
                            outOwnersB3.Add(pos);
                            outlets.Add(copyOutlet);
                        }
                    }
                    pos++;
                }
                else
                {
                    throw new ArgumentException("unexpected module structure");
                }
            }

            /*
             * Now mechanically gather together the GraphAssembly arrays from their various pieces.
             */
            var shape     = new AmorphousShape(inlets.ToImmutable(), outlets.ToImmutable());
            var connStart = insB1.Count;
            var conns     = insB2.Count;
            var outStart  = connStart + conns;
            var count     = outStart + outsB3.Count;

            var ins = new Inlet[count];

            insB1.CopyTo(ins, 0);
            insB2.CopyTo(ins, insB1.Count);

            var inOwners = new int[count];

            inOwnersB1.CopyTo(inOwners, 0);
            inOwnersB2.CopyTo(inOwners, inOwnersB1.Count);
            for (int i = inOwnersB1.Count + inOwnersB2.Count; i < inOwners.Length; i++)
            {
                inOwners[i] = -1;
            }

            var outs = new Outlet[count];

            Array.Copy(outsB2, 0, outs, connStart, conns);
            outsB3.CopyTo(outs, outStart);

            var outOwners = new int[count];

            for (int i = 0; i < connStart; i++)
            {
                outOwners[i] = -1;
            }
            Array.Copy(outOwnersB2, 0, outOwners, connStart, conns);
            outOwnersB3.CopyTo(outOwners, outStart);

            var firstModule = group.First();

            if (!(firstModule is CopiedModule))
            {
                throw new ArgumentException("unexpected module structure");
            }
            var asyncAttrs      = IsAsync((CopiedModule)firstModule) ? new Attributes(Attributes.AsyncBoundary.Instance) : Attributes.None;
            var dispatcher      = GetDispatcher(firstModule);
            var dispatcherAttrs = dispatcher == null ? Attributes.None : new Attributes(dispatcher);
            var attr            = asyncAttrs.And(dispatcherAttrs);

            return(new GraphModule(new GraphAssembly(stages, attributes, ins, inOwners, outs, outOwners), shape, attr, materializedValueIds));
        }