/// <inheritdoc /> public ValueTask OnThreadState <Key, Value, Input, Output, Context, Functions>( SystemState current, SystemState prev, FasterKV <Key, Value, Input, Output, Context, Functions> faster, FasterKV <Key, Value, Input, Output, Context, Functions> .FasterExecutionContext ctx, ClientSession <Key, Value, Input, Output, Context, Functions> clientSession, bool async = true, CancellationToken token = default) where Key : new() where Value : new() where Functions : IFunctions <Key, Value, Input, Output, Context> { switch (current.phase) { case Phase.PREPARE: if (ctx != null) { if (!ctx.markers[EpochPhaseIdx.Prepare]) { if (!faster.RelaxedCPR) { faster.AcquireSharedLatchesForAllPendingRequests(ctx); } ctx.markers[EpochPhaseIdx.Prepare] = true; } faster.epoch.Mark(EpochPhaseIdx.Prepare, current.version); } if (faster.epoch.CheckIsComplete(EpochPhaseIdx.Prepare, current.version)) { faster.GlobalStateMachineStep(current); } break; case Phase.IN_PROGRESS: if (ctx != null) { // Need to be very careful here as threadCtx is changing var _ctx = prev.phase == Phase.IN_PROGRESS ? ctx.prevCtx : ctx; if (!_ctx.markers[EpochPhaseIdx.InProgress]) { faster.AtomicSwitch(ctx, ctx.prevCtx, _ctx.version); faster.InitContext(ctx, ctx.prevCtx.guid, ctx.prevCtx.serialNum); // Has to be prevCtx, not ctx ctx.prevCtx.markers[EpochPhaseIdx.InProgress] = true; } faster.epoch.Mark(EpochPhaseIdx.InProgress, current.version); } // Has to be prevCtx, not ctx if (faster.epoch.CheckIsComplete(EpochPhaseIdx.InProgress, current.version)) { faster.GlobalStateMachineStep(current); } break; case Phase.WAIT_PENDING: if (ctx != null) { if (!faster.RelaxedCPR && !ctx.prevCtx.markers[EpochPhaseIdx.WaitPending]) { if (ctx.prevCtx.HasNoPendingRequests) { ctx.prevCtx.markers[EpochPhaseIdx.WaitPending] = true; } else { break; } } faster.epoch.Mark(EpochPhaseIdx.WaitPending, current.version); } if (faster.epoch.CheckIsComplete(EpochPhaseIdx.WaitPending, current.version)) { faster.GlobalStateMachineStep(current); } break; case Phase.REST: break; } return(default);
/// <inheritdoc /> public void OnThreadState <Key, Value, Input, Output, Context, FasterSession>( SystemState current, SystemState prev, FasterKV <Key, Value> faster, FasterKV <Key, Value> .FasterExecutionContext <Input, Output, Context> ctx, FasterSession fasterSession, List <ValueTask> valueTasks, CancellationToken token = default) where FasterSession : IFasterSession { switch (current.phase) { case Phase.PREPARE: if (ctx != null) { if (!ctx.markers[EpochPhaseIdx.Prepare]) { if (!faster.RelaxedCPR) { faster.AcquireSharedLatchesForAllPendingRequests(ctx); } ctx.markers[EpochPhaseIdx.Prepare] = true; } faster.epoch.Mark(EpochPhaseIdx.Prepare, current.version); } if (faster.epoch.CheckIsComplete(EpochPhaseIdx.Prepare, current.version)) { faster.GlobalStateMachineStep(current); } break; case Phase.IN_PROGRESS: if (ctx != null) { // Need to be very careful here as threadCtx is changing var _ctx = prev.phase == Phase.IN_PROGRESS ? ctx.prevCtx : ctx; var tokens = faster._hybridLogCheckpoint.info.checkpointTokens; if (!faster.SameCycle(current) || tokens == null) { return; } if (!_ctx.markers[EpochPhaseIdx.InProgress]) { faster.AtomicSwitch(ctx, ctx.prevCtx, _ctx.version, tokens); faster.InitContext(ctx, ctx.prevCtx.guid, ctx.prevCtx.serialNum); // Has to be prevCtx, not ctx ctx.prevCtx.markers[EpochPhaseIdx.InProgress] = true; } faster.epoch.Mark(EpochPhaseIdx.InProgress, current.version); } // Has to be prevCtx, not ctx if (faster.epoch.CheckIsComplete(EpochPhaseIdx.InProgress, current.version)) { faster.GlobalStateMachineStep(current); } break; case Phase.WAIT_PENDING: if (ctx != null) { if (!faster.RelaxedCPR && !ctx.prevCtx.markers[EpochPhaseIdx.WaitPending]) { if (ctx.prevCtx.HasNoPendingRequests) { ctx.prevCtx.markers[EpochPhaseIdx.WaitPending] = true; } else { break; } } faster.epoch.Mark(EpochPhaseIdx.WaitPending, current.version); } if (faster.epoch.CheckIsComplete(EpochPhaseIdx.WaitPending, current.version)) { faster.GlobalStateMachineStep(current); } break; case Phase.REST: break; } }