Manages the engine's threads.
Separates the management of ThreadTasks and loops into specialized systems. Should have generally higher performance than the SimpleThreadManager.
Inheritance: IParallelLooper
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public MultithreadedScalingTestDemo(DemosGame game)
            : base(game)
        {
            simulationBuilders = new Func<Space, int>[]
                                     {
                                         BuildPileSimulation,
                                         BuildWallSimulation,
                                         BuildPlanetSimulation
                                     };

            #if WINDOWS
            int coreCountMax = Environment.ProcessorCount;

            testResults = new double[coreCountMax, simulationBuilders.Length];

            int reruns = 1;
            for (int i = 0; i < reruns; i++)
            {
                GC.Collect();
                var threadManager = new SpecializedThreadManager();

                //Try different thread counts.
                for (int j = 0; j < coreCountMax; j++)
                {
                    threadManager.AddThread();
                    for (int k = 0; k < simulationBuilders.Length; k++)
                        testResults[j, k] = RunTest(threadManager, simulationBuilders[k]);
                    GC.Collect();

                }
            }
            #else
            testResults = new double[4, simulationBuilders.Length];
            int reruns = 10;
            for (int i = 0; i < reruns; i++)
            {
                GC.Collect();
                var threadManager = new SpecializedThreadManager();

                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }, null);

                for (int k = 0; k < simulationBuilders.Length; k++)
                    testResults[0, k] += RunTest(threadManager, simulationBuilders[k]);
                GC.Collect();

                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }, null);
                for (int k = 0; k < simulationBuilders.Length; k++)
                    testResults[1, k] += RunTest(threadManager, simulationBuilders[k]);
                GC.Collect();
                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }, null);
                for (int k = 0; k < simulationBuilders.Length; k++)
                    testResults[2, k] += RunTest(threadManager, simulationBuilders[k]);
                GC.Collect();
                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 4 }); }, null);
                for (int k = 0; k < simulationBuilders.Length; k++)
                    testResults[3, k] += RunTest(threadManager, simulationBuilders[k]);
                GC.Collect();
            }
            #endif
        }
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public BroadPhaseMultithreadingTestDemo(DemosGame game)
            : base(game)
        {
            Space.Solver.IterationLimit = 0;

            #if WINDOWS
            int coreCountMax = Environment.ProcessorCount;
            int splitOffsetMax = 6;
            testResults = new double[coreCountMax, splitOffsetMax + 1];

            int reruns = 10;
            for (int i = 0; i < reruns; i++)
            {
                GC.Collect();
                var threadManager = new SpecializedThreadManager();

                //Try different thread counts.
                for (int j = 0; j < coreCountMax; j++)
                {
                    threadManager.AddThread();
                    //Try different split levels.);
                    for (int k = 0; k <= splitOffsetMax; k++)
                    {
                        testResults[j, k] += RunTest(k, threadManager);
                        GC.Collect();
                    }
                }
            }

            for (int i = 0; i < testResults.GetLength(0); i++)
            {
                for (int j = 0; j < testResults.GetLength(1); j++)
                {
                    testResults[i, j] /= reruns;
                }
            }
            #else
            int splitOffsetMax = 6;

            testResults = new double[4, splitOffsetMax + 1];

            int reruns = 10;
            for (int i = 0; i < reruns; i++)
            {
                var threadManager = new SpecializedThreadManager();
                GC.Collect();

                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }, null);
                for (int j = 0; j <= splitOffsetMax; j++)
                {
                    testResults[0, j] += RunTest(j, threadManager);
                    GC.Collect();
                }
                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }, null);
                for (int j = 0; j <= splitOffsetMax; j++)
                {
                    testResults[1, j] += RunTest(j, threadManager);
                    GC.Collect();
                }
                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }, null);
                for (int j = 0; j <= splitOffsetMax; j++)
                {
                    testResults[2, j] += RunTest(j, threadManager);
                    GC.Collect();
                }
                threadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 4 }); }, null);
                for (int j = 0; j <= splitOffsetMax; j++)
                {
                    testResults[3, j] += RunTest(j, threadManager);
                    GC.Collect();
                }
            }

            for (int i = 0; i < testResults.GetLength(0); i++)
            {
                for (int j = 0; j < testResults.GetLength(1); j++)
                {
                    testResults[i,j] /= reruns;
                }
            }
            #endif
        }