From 57be08f16d380e7bf8ddede1d55b384bdfec3869 Mon Sep 17 00:00:00 2001 From: Sarbian Date: Tue, 18 Jul 2017 00:15:36 +0200 Subject: [PATCH] Fix a stupid race condition that I fixed in the past but clealy did not commit... And some inital work on the use of OnWaitForFixedUpdate --- MechJeb2/ComputerModule.cs | 4 ++ MechJeb2/MechJebModuleInfoItems.cs | 5 +- MechJeb2/MechJebModuleStageStats.cs | 73 ++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/MechJeb2/ComputerModule.cs b/MechJeb2/ComputerModule.cs index 8127a8bc2..d227b14d1 100644 --- a/MechJeb2/ComputerModule.cs +++ b/MechJeb2/ComputerModule.cs @@ -113,6 +113,10 @@ public virtual void OnFixedUpdate() { } + public virtual void OnWaitForFixedUpdate() + { + } + public virtual void OnUpdate() { } diff --git a/MechJeb2/MechJebModuleInfoItems.cs b/MechJeb2/MechJebModuleInfoItems.cs index e5cc085ae..7c5dfdf80 100644 --- a/MechJeb2/MechJebModuleInfoItems.cs +++ b/MechJeb2/MechJebModuleInfoItems.cs @@ -844,11 +844,12 @@ public void AllStageStats() MechJebModuleStageStats stats = core.GetComputerModule(); if (Event.current.type == EventType.Layout) { - vacStats = stats.vacStats; - atmoStats = stats.atmoStats; stats.RequestUpdate(this); } + vacStats = stats.vacStats; + atmoStats = stats.atmoStats; + Profiler.EndSample(); Profiler.BeginSample("AllStageStats.UI1"); diff --git a/MechJeb2/MechJebModuleStageStats.cs b/MechJeb2/MechJebModuleStageStats.cs index 584b50666..9e684ad50 100644 --- a/MechJeb2/MechJebModuleStageStats.cs +++ b/MechJeb2/MechJebModuleStageStats.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading; +using UnityEngine; namespace MuMech { @@ -18,21 +19,35 @@ public class MechJebModuleStageStats : ComputerModule public FuelFlowSimulation.Stats[] atmoStats = { }; public FuelFlowSimulation.Stats[] vacStats = { }; + + // Those are used to store the next result from the thread since we must move result + // to atmoStats/vacStats only in the main thread. + private FuelFlowSimulation.Stats[] newAtmoStats; + private FuelFlowSimulation.Stats[] newVacStats; + private bool resultReady = false; + public void RequestUpdate(object controller, bool wait = false) { users.Add(controller); updateRequested = true; - if (HighLogic.LoadedSceneIsEditor && editorBody != null) + IsResultReady(); + + // In the editor this is our only entry point + if (HighLogic.LoadedSceneIsEditor) { - if (TryStartSimulation() && wait) + TryStartSimulation(); + } + + // wait means the code needs some result to run so we wait if we do not have any result yet + if (wait && atmoStats.Length == 0 && (simulationRunning || TryStartSimulation())) + { + while (simulationRunning) { - while (simulationRunning) - { - // wait for a sim to be ready. Risked ? - Thread.Sleep(1); - } + // wait for a sim to be ready. Risked ? + Thread.Sleep(1); } + IsResultReady(); } } @@ -96,12 +111,36 @@ public override void OnModuleDisabled() public override void OnFixedUpdate() { + // Check if we have a result ready from the previous physic frame + IsResultReady(); + TryStartSimulation(); } - public bool TryStartSimulation() + public override void OnWaitForFixedUpdate() + { + // Check if we managed to get a result while the physic frame was running + IsResultReady(); + } + + public override void OnUpdate() + { + IsResultReady(); + } + + private void IsResultReady() { - if ((HighLogic.LoadedSceneIsEditor || (vessel != null && vessel.isActiveVessel)) && !simulationRunning) + if (resultReady) + { + atmoStats = newAtmoStats; + vacStats = newVacStats; + resultReady = false; + } + } + + private bool TryStartSimulation() + { + if (!simulationRunning && ((HighLogic.LoadedSceneIsEditor && editorBody != null) || (vessel != null && vessel.isActiveVessel))) { //We should be running simulations periodically, but one is not running right now. //Check if enough time has passed since the last one to start a new one: @@ -128,9 +167,11 @@ public bool TryStartSimulation() protected void StartSimulation() { + Profiler.BeginSample("StartSimulation"); try { simulationRunning = true; + resultReady = false; stopwatch.Start(); //starts a timer that times how long the simulation takes //Create two FuelFlowSimulations, one for vacuum and one for atmosphere @@ -149,12 +190,18 @@ protected void StartSimulation() vessel.UpdateResourceSetsIfDirty(); } + Profiler.BeginSample("StartSimulation_Init"); + sims[0].Init(parts, dVLinearThrust); sims[1].Init(parts, dVLinearThrust); + Profiler.EndSample(); + //Run the simulation in a separate thread ThreadPool.QueueUserWorkItem(RunSimulation, sims); + //Profiler.BeginSample("StartSimulation_Run"); //RunSimulation(sims); + //Profiler.EndSample(); } catch (Exception e) { @@ -169,6 +216,7 @@ protected void StartSimulation() stopwatch.Start(); simulationRunning = false; } + Profiler.EndSample(); } protected void RunSimulation(object o) @@ -182,10 +230,8 @@ protected void RunSimulation(object o) double mach = HighLogic.LoadedSceneIsEditor ? this.mach : vessel.mach; //Run the simulation - FuelFlowSimulation.Stats[] newAtmoStats = sims[0].SimulateAllStages(1.0f, staticPressureKpa, atmDensity, mach); - FuelFlowSimulation.Stats[] newVacStats = sims[1].SimulateAllStages(1.0f, 0.0, 0.0 , mach); - atmoStats = newAtmoStats; - vacStats = newVacStats; + newAtmoStats = sims[0].SimulateAllStages(1.0f, staticPressureKpa, atmDensity, mach); + newVacStats = sims[1].SimulateAllStages(1.0f, 0.0, 0.0, mach); } catch (Exception e) { @@ -202,6 +248,7 @@ protected void RunSimulation(object o) //start the stopwatch that will count off this delay stopwatch.Start(); + resultReady = true; simulationRunning = false; } }