/// <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); } } // end of WriteFunctions()