Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DynamicBuildStep.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System.Collections.Generic;
4 using System.Linq;
5 using System.Threading;
6 using System.Threading.Tasks;
7 
8 namespace SiliconStudio.BuildEngine
9 {
11  {
12  private readonly IBuildStepProvider buildStepProvider;
13 
14  // TODO: centralize this infomation in the Builder.
15  private const int MaxParallelism = 8;
16 
17  /// <summary>
18  /// The <see cref="AutoResetEvent"/> used to notify the dynamic build step that new work is requested.
19  /// </summary>
20  private readonly AutoResetEvent newWorkAvailable = new AutoResetEvent(false);
21 
22  public DynamicBuildStep(IBuildStepProvider buildStepProvider)
23  {
24  this.buildStepProvider = buildStepProvider;
25  }
26 
27  /// <summary>
28  /// Notify the dynamic build step new work is available.
29  /// </summary>
30  public void NotifyNewWorkAvailable()
31  {
32  newWorkAvailable.Set();
33  }
34 
35  public async override Task<ResultStatus> Execute(IExecuteContext executeContext, BuilderContext builderContext)
36  {
37  var buildStepsToWait = new List<BuildStep>();
38 
39  while (true)
40  {
41  // interrupt the build if cancellation is required.
42  if (executeContext.CancellationTokenSource.Token.IsCancellationRequested)
43  return ResultStatus.Cancelled;
44 
45  // wait for a task to complete
46  if (buildStepsToWait.Count >= MaxParallelism)
47  await CompleteOneBuildStep(executeContext, buildStepsToWait);
48 
49  // Transform item into build step
50  var buildStep = buildStepProvider.GetNextBuildStep();
51 
52  // No job => passively wait
53  if (buildStep == null)
54  {
55  newWorkAvailable.WaitOne();
56 
57  continue;
58  }
59 
60  // Safeguard if the provided build step is already processed
61  if(buildStep.Processed)
62  continue;
63 
64  if (buildStep is WaitBuildStep)
65  {
66  // wait for all the task in execution to complete
67  while (buildStepsToWait.Count>0)
68  await CompleteOneBuildStep(executeContext, buildStepsToWait);
69 
70  continue;
71  }
72 
73  // Schedule build step
74  executeContext.ScheduleBuildStep(buildStep);
75  buildStepsToWait.Add(buildStep);
76  }
77  }
78 
79  /// <inheritdoc/>
80  public override BuildStep Clone()
81  {
82  var clone = new DynamicBuildStep(buildStepProvider);
83  return clone;
84  }
85 
86  /// <inheritdoc/>
87  public override string ToString()
88  {
89  return "DynamicBuildStep";
90  }
91 
92  private async Task CompleteOneBuildStep(IExecuteContext executeContext, List<BuildStep> buildStepsToWait)
93  {
94  // Too many build steps, wait for one to finish
95  var completeBuildStep = await Task.WhenAny(buildStepsToWait.Select(x => x.ExecutedAsync()));
96 
97  // Clear inputs and outputs (each step is independent)
98  inputObjects.Clear();
99  outputObjects.Clear();
100 
101  // Process input and outputs
102  await CompleteCommands(executeContext, new List<BuildStep> { completeBuildStep.Result });
103 
104  // Merge outputs with index file
105  IndexFileCommand.MergeOutputObjects(outputObjects);
106 
107  // Remove from list of build step to wait
108  buildStepsToWait.Remove(completeBuildStep.Result);
109  }
110  }
111 }
A BuildStep that can spawn multiple BuildStep. Input and output tracking and merging will be performe...
async override Task< ResultStatus > Execute(IExecuteContext executeContext, BuilderContext builderContext)
Execute the BuildStep, usually resulting in scheduling tasks in the scheduler
override BuildStep Clone()
Clone this Build Step.
When embedded in a EnumerableBuildStep, this build step will force all previous computations to be fi...
void NotifyNewWorkAvailable()
Notify the dynamic build step new work is available.
CancellationTokenSource CancellationTokenSource
This interface describes a class that is capable of providing build steps to a DynamicBuildStep.
DynamicBuildStep(IBuildStepProvider buildStepProvider)