using XFEEDToolBox.Core.Execution; // A real runner may remain Running while its first operation is held here. // None of the four mutation paths is ever forwarded to the production driver. internal sealed class TradePauseMutationBarrier(ITradeCommandDriver production,ITradeRunMenuRecovery menu):ITradeCommandDriver,ITradeRunMenuRecovery { private readonly TaskCompletionSource reached=new(TaskCreationOptions.RunContinuationsAsynchronously); private int buys,sells,travels,services; internal Task FirstMutationHeld=>reached.Task; internal int BlockedBuys=>Volatile.Read(ref buys); internal int BlockedSells=>Volatile.Read(ref sells); internal int BlockedTravels=>Volatile.Read(ref travels); internal int BlockedServices=>Volatile.Read(ref services); internal const int ForwardedMutations=0; public Task PreflightAsync(CancellationToken token)=>production.PreflightAsync(token); public IDisposable EnterRunningMenuRecovery(Func isRunning,CancellationToken token)=>menu.EnterRunningMenuRecovery(isRunning,token); public async Task ServiceDockedAsync(DockedServiceRequest request,Func beforeInput,CancellationToken token) {await beforeInput(token);Interlocked.Increment(ref services);reached.TrySetResult();await Task.Delay(Timeout.Infinite,token);} public async Task ExecuteAsync(TradeAction action,Func beforeInput,CancellationToken token) { await beforeInput(token); switch(action.Kind) { case TradeActionKind.Buy:Interlocked.Increment(ref buys);break; case TradeActionKind.Sell:Interlocked.Increment(ref sells);break; case TradeActionKind.Travel:Interlocked.Increment(ref travels);break; default:throw new InvalidOperationException("Unknown trade mutation was refused."); } reached.TrySetResult();await Task.Delay(Timeout.Infinite,token); } public Task ReleaseAllAsync()=>production.ReleaseAllAsync(); }