예제 #1
0
파일: functions.cs 프로젝트: Sciumo/gaigen
        /// <summary>
        /// Writes code for all functions to <c>cgd.m_defSB</c>, <c>cgd.m_inlineDefSB and</c> <c>cgd.m_declSB</c>.
        /// 
        /// Takes an explicit list of functions (used by  <c>TestSuite.GenerateCode()</c>).
        /// </summary>
        /// <param name="S"></param>
        /// <param name="cgd">Generated code goes here</param>
        /// <param name="FGI">Info about what plugin should implement what function 
        /// The member variables are initialized by this function. <c>FGI</c> can be null when
        /// no testing code is generated. This allows the memory of the FunctionGenerators to be released
        /// earlier on.</param>
        /// <param name="plugins">The available function generators.</param>
        /// <param name="functions">List of <c>G25.fgs</c> to implement.</param>
        public static void WriteFunctions(
            Specification S,
            G25.CG.Shared.CGdata cgd,
            G25.CG.Shared.FunctionGeneratorInfo FGI,
            List<G25.CG.Shared.BaseFunctionGenerator> plugins,
            List<G25.fgs> functions)
        {
            // first split functions into converters and regular functions
            List<G25.fgs> converterFGS = new List<fgs>();
            List<G25.fgs> functionFGS = new List<fgs>();
            foreach (G25.fgs F in functions)
            {
                if (F.IsConverter(S)) // is 'F' a converter (underscore constructor)?
                    converterFGS.Add(F);
                else functionFGS.Add(F);
            }

            // store converterFGS and functionFGS in FGI, for later use by TestSuite.GenerateCode()
            if (FGI != null)
            {
                FGI.m_converterFGS = converterFGS;
                FGI.m_functionFGS = functionFGS;
            }

            // start threads to generate code for all converters
            Thread[] converterThreads = new Thread[converterFGS.Count];
            Converter[] converters = new Converter[converterFGS.Count];
            for (int f = 0; f < converterFGS.Count; f++)
            {
                G25.fgs F = converterFGS[f];
                converters[f] = new Converter(S, cgd, F);
                converterThreads[f] = new Thread(converters[f].WriteConverter);
            }
            G25.CG.Shared.Threads.StartThreadArray(converterThreads);

            // find out which plugin can implement which FGS
            Thread[] functionThreads = new Thread[functionFGS.Count];
            G25.CG.Shared.BaseFunctionGenerator[] functionGenerators = new G25.CG.Shared.BaseFunctionGenerator[functionFGS.Count];
            G25.CG.Shared.CGdata[] functionCgd = new G25.CG.Shared.CGdata[functionFGS.Count];
            for (int f = 0; f < functionFGS.Count; f++)
            {
                G25.fgs F = functionFGS[f];

                foreach (G25.CG.Shared.BaseFunctionGenerator P in plugins) // check all C plugins
                {
                    if (P.CanImplement(S, F)) // ask them if they can handle 'F'
                    {
                        // get a clean instance of the code generator and initialize it
                        functionGenerators[f] = System.Activator.CreateInstance(P.GetType()) as BaseFunctionGenerator;
                        functionCgd[f] = new G25.CG.Shared.CGdata(cgd); // m_errors and m_missingDependencies will be shared with main cgd!
                        functionGenerators[f].Init(S, F, functionCgd[f]);
                        F.SetSupportedByPlugin();
                        break;
                    }
                }
                if (!F.GetSupportedByPlugin())
                {// no plugin could do 'F': complain about it
                    System.Console.WriteLine("Warning no suitable plugin for function " + F.Name + "; XML specification: ");
                    System.Console.WriteLine("    " + XML.FunctionToXmlString(S, F));
                }
            }

            // store functionGenerators in FGI, for later use by TestSuite.GenerateCode()
            if (FGI != null)
            {
                FGI.m_functionGenerators = functionGenerators;
                FGI.m_functionCgd = functionCgd;
            }

            // run threads for fill-in of functions
            for (int f = 0; f < functionFGS.Count; f++)
            {
                if (functionGenerators[f] == null) continue;
                functionThreads[f] = new Thread(functionGenerators[f].CompleteFGSentryPoint);
            }
            G25.CG.Shared.Threads.StartThreadArray(functionThreads);
            G25.CG.Shared.Threads.JoinThreadArray(functionThreads);
            //G25.CG.Shared.Threads.RunThreadArraySerially(functionThreads);

            // runs thread for dependency check of functions
            for (int f = 0; f < functionFGS.Count; f++)
            {
                if (functionGenerators[f] == null) continue;
                functionThreads[f] = new Thread(functionGenerators[f].CheckDepenciesEntryPoint);
            }
            G25.CG.Shared.Threads.StartThreadArray(functionThreads);
            G25.CG.Shared.Threads.JoinThreadArray(functionThreads);
            //G25.CG.Shared.Threads.RunThreadArraySerially(functionThreads);

            // runs thread for actual code generation of functions
            for (int f = 0; f < functionFGS.Count; f++)
            {
                if (functionGenerators[f] == null) continue;
                functionThreads[f] = new Thread(functionGenerators[f].WriteFunctionEntryPoint);
            }
            G25.CG.Shared.Threads.StartThreadArray(functionThreads);
            //G25.CG.Shared.Threads.RunThreadArraySerially(functionThreads);

            // join all the converter threads:
            G25.CG.Shared.Threads.JoinThreadArray(converterThreads);

            // join all function generation threads
            G25.CG.Shared.Threads.JoinThreadArray(functionThreads);

            // collect all the results from the threads:
            for (int f = 0; f < converters.Length; f++)
            {
                cgd.m_declSB.Append(converters[f].m_declSB);
                cgd.m_defSB.Append(converters[f].m_defSB);
                cgd.m_inlineDefSB.Append(converters[f].m_inlineDefSB);
                cgd.MergeErrors(converters[f].m_cgd);
            }

            // collect all the results from the threads:
            for (int f = 0; f < functionCgd.Length; f++)
            {
                if (functionGenerators[f] == null) continue;
                cgd.m_declSB.Append(functionCgd[f].m_declSB);
                cgd.m_defSB.Append(functionCgd[f].m_defSB);
                cgd.m_inlineDefSB.Append(functionCgd[f].m_inlineDefSB);
            }
        }