Skip to content

Commit

Permalink
Fix macro editor thread safety
Browse files Browse the repository at this point in the history
  • Loading branch information
WorkingRobot committed Nov 14, 2023
1 parent 9806139 commit 0a55e87
Showing 1 changed file with 53 additions and 4 deletions.
57 changes: 53 additions & 4 deletions Craftimizer/Windows/MacroEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public SimulationReliablity GetReliability(in SimulationState initialState, IEnu
Reliability ??=
new(initialState, actionSet, Service.Configuration.ReliabilitySimulationCount, recipeData);
};

private List<SimulatedActionStep> Macro { get; set; } = new();
private SimulationState InitialState { get; set; }
private SimulationState State => Macro.Count > 0 ? Macro[^1].State : InitialState;
Expand All @@ -191,6 +191,8 @@ public SimulationReliablity GetReliability(in SimulationState initialState, IEnu
private CancellationTokenSource? SolverTokenSource { get; set; }
private Exception? SolverException { get; set; }
private int? SolverStartStepCount { get; set; }
private object? SolverQueueLock { get; set; }
private List<SimulatedActionStep>? SolverQueuedSteps { get; set; }
private bool SolverRunning => SolverTokenSource != null;

private IDalamudTextureWrap ExpertBadge { get; }
Expand Down Expand Up @@ -255,6 +257,11 @@ public override void OnClose()
SolverTokenSource?.Cancel();
}

public override void Update()
{
TryFlushSolvedSteps();
}

public override void Draw()
{
var modifiedInput = false;
Expand Down Expand Up @@ -1577,6 +1584,16 @@ private void CalculateBestMacro()
SolverTokenSource?.Cancel();
SolverTokenSource = new();
SolverException = null;
if (SolverQueueLock is { })
{
lock (SolverQueueLock)
{
SolverQueuedSteps!.Clear();
SolverQueueLock = null;
}
}
SolverQueueLock = new();
SolverQueuedSteps ??= new();

RevertPreviousMacro();

Expand Down Expand Up @@ -1622,7 +1639,7 @@ private void CalculateBestMacroTask(SimulationState state, CancellationToken tok

var solver = new Solver.Solver(config, state) { Token = token };
solver.OnLog += Log.Debug;
solver.OnNewAction += a => AddStep(a, isSolver: true);
solver.OnNewAction += QueueSolverStep;
solver.Start();
_ = solver.GetTask().GetAwaiter().GetResult();

Expand Down Expand Up @@ -1655,11 +1672,11 @@ private static Sim CreateSim() =>
private static Sim CreateSim(in SimulationState state) =>
Service.Configuration.ConditionRandomness ? new Sim() { State = state } : new SimNoRandom() { State = state };

private void AddStep(ActionType action, int index = -1, bool isSolver = false)
private void AddStep(ActionType action, int index = -1)
{
if (index < -1 || index >= Macro.Count)
throw new ArgumentOutOfRangeException(nameof(index));
if (!isSolver && SolverRunning)
if (SolverRunning)
throw new InvalidOperationException("Cannot add steps while solver is running");
if (!SolverRunning)
SolverStartStepCount = null;
Expand All @@ -1680,6 +1697,38 @@ private void AddStep(ActionType action, int index = -1, bool isSolver = false)
}
}

private void QueueSolverStep(ActionType action)
{
if (!SolverRunning)
throw new InvalidOperationException("Cannot queue steps while solver isn't running");
lock (SolverQueueLock!)
{
var lastState = SolverQueuedSteps!.Count > 0 ? SolverQueuedSteps[^1].State : State;
SolverQueuedSteps.Add(new(action, CreateSim(), lastState, out _));
}
}

private void TryFlushSolvedSteps()
{
if (SolverQueueLock == null)
return;

lock (SolverQueueLock!)
{
if (SolverQueuedSteps!.Count > 0)
{
Macro.AddRange(SolverQueuedSteps);
SolverQueuedSteps.Clear();
}

if (!SolverRunning)
{
SolverQueuedSteps.Clear();
SolverQueueLock = null;
}
}
}

private void RemoveStep(int index)
{
if (index < 0 || index >= Macro.Count)
Expand Down

1 comment on commit 0a55e87

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark

Benchmark suite Current: 0a55e87 Previous: 4bf7397 Ratio
Craftimizer.Benchmark.Bench.Solve(State: 5372D31C98FA4C357F54029912394B0F5ECBE94AEC9D12C1C2B7F453C62ACD2F, Config: B75845A5DEDC79F3C98FE35F28206855B0EF4E065555FAF2AA129AED115B7744) 1349767253.3333333 ns (± 2685077.6165601583) 1480306700 ns (± 23679878.252854258) 0.91
Craftimizer.Benchmark.Bench.Solve(State: 5372D31C98FA4C357F54029912394B0F5ECBE94AEC9D12C1C2B7F453C62ACD2F, Config: B75845A5DEDC79F3C98FE35F28206855B0EF4E065555FAF2AA129AED115B7744) 999295107.1428572 ns (± 3589995.4762054817) 1480306700 ns (± 23679878.252854258) 0.68
Craftimizer.Benchmark.Bench.Solve(State: 99B0F1AD46A18B4D8262F9BA75ABE23507217C2F20FBF895A49282DDFEF50190, Config: B75845A5DEDC79F3C98FE35F28206855B0EF4E065555FAF2AA129AED115B7744) 1637261286.6666667 ns (± 4459211.507152785) 1450385066.6666667 ns (± 6712458.243197247) 1.13
Craftimizer.Benchmark.Bench.Solve(State: 99B0F1AD46A18B4D8262F9BA75ABE23507217C2F20FBF895A49282DDFEF50190, Config: B75845A5DEDC79F3C98FE35F28206855B0EF4E065555FAF2AA129AED115B7744) 1147882842.857143 ns (± 6360059.854666861) 1450385066.6666667 ns (± 6712458.243197247) 0.79

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.