diff --git a/Bullseye/Internal/TargetCollection.cs b/Bullseye/Internal/TargetCollection.cs index 1ba0e7ba..7a47680e 100644 --- a/Bullseye/Internal/TargetCollection.cs +++ b/Bullseye/Internal/TargetCollection.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -27,7 +28,7 @@ public async Task RunAsync(IEnumerable names, bool skipDependencies, boo try { - var runningTargets = new Dictionary(); + var runningTargets = new ConcurrentDictionary(); using (var sync = new SemaphoreSlim(1, 1)) { @@ -54,7 +55,7 @@ public async Task RunAsync(IEnumerable names, bool skipDependencies, boo await log.Succeeded(names).Tax(); } - private async Task RunAsync(string name, IEnumerable explicitTargets, bool skipDependencies, bool dryRun, bool parallel, Logger log, Func messageOnly, Dictionary runningTargets, SemaphoreSlim sync, Stack dependencyStack) + private async Task RunAsync(string name, IEnumerable explicitTargets, bool skipDependencies, bool dryRun, bool parallel, Logger log, Func messageOnly, ConcurrentDictionary runningTargets, SemaphoreSlim sync, Stack dependencyStack) { dependencyStack.Push(name); @@ -66,22 +67,7 @@ private async Task RunAsync(string name, IEnumerable explicitTargets, bo return; } - bool gotValue; - Task runningTarget; - - // cannot use WaitAsync() as it is not reentrant - sync.Wait(); - - try - { - gotValue = runningTargets.TryGetValue(name, out runningTarget); - } - finally - { - _ = sync.Release(); - } - - if (gotValue) + if (runningTargets.TryGetValue(name, out var runningTarget)) { await log.Verbose(dependencyStack, "Awaiting...").Tax(); await runningTarget.Tax(); @@ -117,7 +103,7 @@ private async Task RunAsync(string name, IEnumerable explicitTargets, bo if (!runningTargets.TryGetValue(name, out runningTarget)) { runningTarget = target.RunAsync(dryRun, parallel, log, messageOnly); - runningTargets.Add(name, runningTarget); + _ = runningTargets.TryAdd(name, runningTarget); } } finally diff --git a/BullseyeSmokeTester/Program.cs b/BullseyeSmokeTester/Program.cs index e39638ce..4eb3747e 100644 --- a/BullseyeSmokeTester/Program.cs +++ b/BullseyeSmokeTester/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; @@ -101,8 +102,24 @@ targets.Add("def", DependsOn("abc"), () => Console.Out.WriteLine("def")); targets.Add("default", DependsOn("def")); +var largeGraph = new Targets(); +var largeGraphTargetNames = new List(); + +foreach (var name in Enumerable.Range(1, 30).Select(i => i.ToString(CultureInfo.InvariantCulture))) +{ + largeGraph.Add(name, largeGraphTargetNames.TakeLast(2), () => { }); + largeGraphTargetNames.Add(name); +} + +largeGraph.Add("large-graph", DependsOn(largeGraphTargetNames.Last())); + var (options, targetNames) = Options.Parse(args); +if (targetNames.Contains("large-graph")) +{ + await largeGraph.RunAndExitAsync(targetNames, options); +} + if (!options.ShowHelp) { await targets.RunWithoutExitingAsync(targetNames, options); diff --git a/build.cmd b/build.cmd index e4713350..09120d14 100644 --- a/build.cmd +++ b/build.cmd @@ -23,6 +23,8 @@ dotnet run -c Release --no-build -p BullseyeSmokeTester -- --verbose || goto :er dotnet run -c Release --no-build -p BullseyeSmokeTester -- -h --verbose || goto :error dotnet run -c Release --no-build -p BullseyeSmokeTester -- -h --verbose --no-color || goto :error +dotnet run -c Release --no-build -p BullseyeSmokeTester -- large-graph --verbose --parallel || goto :error + dotnet run -c Release --no-build -p BullseyeSmokeTester.DragonFruit -- --help || goto :error dotnet run -c Release --no-build -p BullseyeSmokeTester.DragonFruit -- --foo bar --verbose --targets build || goto :error diff --git a/build.sh b/build.sh index f0335c1f..cdfc0d9e 100755 --- a/build.sh +++ b/build.sh @@ -25,6 +25,8 @@ dotnet run -c Release --no-build -p BullseyeSmokeTester -- --verbose dotnet run -c Release --no-build -p BullseyeSmokeTester -- -h --verbose dotnet run -c Release --no-build -p BullseyeSmokeTester -- -h --verbose --no-color +dotnet run -c Release --no-build -p BullseyeSmokeTester -- large-graph --verbose --parallel + dotnet run -c Release --no-build -p BullseyeSmokeTester.DragonFruit -- --help dotnet run -c Release --no-build -p BullseyeSmokeTester.DragonFruit -- --foo bar --verbose --targets build