public static int Execute(string ActionsFileName, int MaxProcesses, bool bStopOnErrors) { List <BuildAction> Actions = ReadActions(ActionsFileName); CommandUtils.Log("Building with {0} {1}...", MaxProcesses, (MaxProcesses == 1)? "process" : "processes"); // Create the list of things to process List <BuildAction> QueuedActions = new List <BuildAction>(); foreach (BuildAction Action in Actions) { if (Action.MissingDependencyCount == 0) { QueuedActions.Add(Action); } } // Create a job object for all the child processes int ExitCode = 0; string CurrentPrefix = ""; Dictionary <BuildActionExecutor, Thread> ExecutingActions = new Dictionary <BuildActionExecutor, Thread>(); List <BuildActionExecutor> CompletedActions = new List <BuildActionExecutor>(); using (ManualResetEvent CompletedEvent = new ManualResetEvent(false)) { while (QueuedActions.Count > 0 || ExecutingActions.Count > 0) { // Sort the actions by the number of things dependent on them QueuedActions.Sort((A, B) => (A.TotalDependants == B.TotalDependants)? (B.SortIndex - A.SortIndex) : (B.TotalDependants - A.TotalDependants)); // Create threads up to the maximum number of actions while (ExecutingActions.Count < MaxProcesses && QueuedActions.Count > 0) { BuildAction Action = QueuedActions[QueuedActions.Count - 1]; QueuedActions.RemoveAt(QueuedActions.Count - 1); BuildActionExecutor ExecutingAction = new BuildActionExecutor(Action, CompletedEvent, CompletedActions); Thread ExecutingThread = new Thread(() => { ExecutingAction.Run(); }); ExecutingThread.Name = String.Format("Build:{0}", Action.Caption); ExecutingThread.Start(); ExecutingActions.Add(ExecutingAction, ExecutingThread); } // Wait for something to finish CompletedEvent.WaitOne(); // Wait for something to finish and flush it to the log lock (CompletedActions) { foreach (BuildActionExecutor CompletedAction in CompletedActions) { // Join the thread Thread CompletedThread = ExecutingActions[CompletedAction]; CompletedThread.Join(); ExecutingActions.Remove(CompletedAction); // Write it to the log if (CompletedAction.LogLines.Count > 0) { if (CurrentPrefix != CompletedAction.Action.GroupPrefix) { CurrentPrefix = CompletedAction.Action.GroupPrefix; CommandUtils.Log(CurrentPrefix); } foreach (string LogLine in CompletedAction.LogLines) { CommandUtils.Log(LogLine); } } // Check the exit code if (CompletedAction.ExitCode == 0) { // Mark all the dependents as done foreach (BuildAction DependantAction in CompletedAction.Action.Dependants) { if (--DependantAction.MissingDependencyCount == 0) { QueuedActions.Add(DependantAction); } } } else { // Update the exit code if it's not already set if (ExitCode == 0) { ExitCode = CompletedAction.ExitCode; } } } CompletedActions.Clear(); } // If we've already got a non-zero exit code, clear out the list of queued actions so nothing else will run if (ExitCode != 0 && bStopOnErrors) { QueuedActions.Clear(); } } } return(ExitCode); }
public static int Execute(string ActionsFileName, int MaxProcesses) { List<BuildAction> Actions = ReadActions(ActionsFileName); CommandUtils.Log("Building with {0} {1}...", MaxProcesses, (MaxProcesses == 1)? "process" : "processes"); // Create the list of things to process List<BuildAction> QueuedActions = new List<BuildAction>(); foreach(BuildAction Action in Actions) { if(Action.MissingDependencyCount == 0) { QueuedActions.Add(Action); } } // Create a job object for all the child processes int ExitCode = 0; string CurrentPrefix = ""; Dictionary<BuildActionExecutor, Thread> ExecutingActions = new Dictionary<BuildActionExecutor,Thread>(); List<BuildActionExecutor> CompletedActions = new List<BuildActionExecutor>(); using(ManualResetEvent CompletedEvent = new ManualResetEvent(false)) { while(QueuedActions.Count > 0 || ExecutingActions.Count > 0) { // Sort the actions by the number of things dependent on them QueuedActions.Sort((A, B) => (A.TotalDependants == B.TotalDependants)? (B.SortIndex - A.SortIndex) : (B.TotalDependants - A.TotalDependants)); // Create threads up to the maximum number of actions while(ExecutingActions.Count < MaxProcesses && QueuedActions.Count > 0) { BuildAction Action = QueuedActions[QueuedActions.Count - 1]; QueuedActions.RemoveAt(QueuedActions.Count - 1); BuildActionExecutor ExecutingAction = new BuildActionExecutor(Action, CompletedEvent, CompletedActions); Thread ExecutingThread = new Thread(() => { ExecutingAction.Run(); }); ExecutingThread.Name = String.Format("Build:{0}", Action.Caption); ExecutingThread.Start(); ExecutingActions.Add(ExecutingAction, ExecutingThread); } // Wait for something to finish CompletedEvent.WaitOne(); // Wait for something to finish and flush it to the log lock(CompletedActions) { foreach(BuildActionExecutor CompletedAction in CompletedActions) { // Join the thread Thread CompletedThread = ExecutingActions[CompletedAction]; CompletedThread.Join(); ExecutingActions.Remove(CompletedAction); // Write it to the log if(CompletedAction.LogLines.Count > 0) { if(CurrentPrefix != CompletedAction.Action.GroupPrefix) { CurrentPrefix = CompletedAction.Action.GroupPrefix; CommandUtils.Log(CurrentPrefix); } foreach(string LogLine in CompletedAction.LogLines) { CommandUtils.Log(LogLine); } } // Check the exit code if(CompletedAction.ExitCode == 0) { // Mark all the dependents as done foreach(BuildAction DependantAction in CompletedAction.Action.Dependants) { if(--DependantAction.MissingDependencyCount == 0) { QueuedActions.Add(DependantAction); } } } else { // Update the exit code if it's not already set if(ExitCode == 0) { ExitCode = CompletedAction.ExitCode; } } } CompletedActions.Clear(); } // If we've already got a non-zero exit code, clear out the list of queued actions so nothing else will run if(ExitCode != 0) { QueuedActions.Clear(); } } } return ExitCode; }