public void TestFromFailToNotAllowedTransitions() { var taskState = new TaskStateMachine(); taskState.MoveNext(TaskStateEvent.SubmittedTask); taskState.MoveNext(TaskStateEvent.RunningTask); taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError); Assert.True(taskState.CurrentState.Equals(TaskState.TaskFailedByEvaluatorFailure), "Failed to move to TaskFailedByEvaluatorFailure state."); Action moveNext = () => taskState.MoveNext(TaskStateEvent.RunningTask); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.ClosedTask); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.CompletedTask); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.SubmittedTask); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.FailedTaskAppError); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.FailedTaskCommunicationError); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.FailedTaskSystemError); Assert.Throws <TaskStateTransitionException>(moveNext); }
/// <summary> /// Construct a TaskInfo that wraps task state, task configuration, and active context for submitting the task /// </summary> /// <param name="taskState"></param> /// <param name="config"></param> /// <param name="context"></param> internal TaskInfo(TaskStateMachine taskState, IConfiguration config, IActiveContext context) { _taskState = taskState; _taskConfiguration = config; _activeContext = context; TimeStateUpdated = DateTime.Now; }
public void TestRunningToCloseToFailedTaskSystemErrorScenario() { var taskState = new TaskStateMachine(); taskState.MoveNext(TaskStateEvent.SubmittedTask); taskState.MoveNext(TaskStateEvent.RunningTask); taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskSystemError).Equals(TaskState.TaskClosedByDriver), "Failed to move from WaitingTaskToClose to TaskClosedByDriver state with FailedTaskSystemError."); }
public void TestRunningToFailByEvaluatorScenario() { var taskState = new TaskStateMachine(); taskState.MoveNext(TaskStateEvent.SubmittedTask); taskState.MoveNext(TaskStateEvent.RunningTask); Assert.True(taskState.MoveNext(TaskStateEvent.FailedTaskEvaluatorError).Equals(TaskState.TaskFailedByEvaluatorFailure), "Failed to move from RunningTask to TaskFailedByEvaluatorFailure state with FailedTaskEvaluatorError."); Assert.True(taskState.IsFinalState(), "TaskFailedByEvaluatorFailure should be a final state."); }
public void TestRunningToWaitingTaskToCloseToComplete() { var taskState = new TaskStateMachine(); taskState.MoveNext(TaskStateEvent.SubmittedTask); taskState.MoveNext(TaskStateEvent.RunningTask); taskState.MoveNext(TaskStateEvent.WaitingTaskToClose); taskState.MoveNext(TaskStateEvent.CompletedTask); Assert.Equal(TaskState.TaskClosedByDriver, taskState.CurrentState); }
public void TestRunningToCloseScenario() { var taskState = new TaskStateMachine(); taskState.MoveNext(TaskStateEvent.SubmittedTask); taskState.MoveNext(TaskStateEvent.RunningTask); Assert.True(taskState.MoveNext(TaskStateEvent.WaitingTaskToClose).Equals(TaskState.TaskWaitingForClose), "Failed to move from RunningTask to TaskWaitingForClose state."); Assert.False(taskState.IsFinalState(), "TaskWaitingForClose should not be a final state."); Assert.True(taskState.MoveNext(TaskStateEvent.ClosedTask).Equals(TaskState.TaskClosedByDriver), "Failed to move from TaskWaitingForClose to TaskClosedByDriver state."); Assert.True(taskState.IsFinalState(), "TaskClosedByDriver should be a final state."); }
public void TestNewToCompleteScenario() { var taskState = new TaskStateMachine(); Assert.True(taskState.CurrentState.Equals(TaskState.TaskNew), "State of newly created task should be TaskNew"); Assert.False(taskState.IsFinalState(), "TaskNew should not be a final state."); Assert.True(taskState.MoveNext(TaskStateEvent.SubmittedTask).Equals(TaskState.TaskSubmitted), "Failed to move from TaskNew to TaskSubmitted state."); Assert.False(taskState.IsFinalState(), "TaskSubmitted should not be a final state."); Assert.True(taskState.MoveNext(TaskStateEvent.RunningTask).Equals(TaskState.TaskRunning), "Failed to move from TaskSubmitted to TaskRunning state."); Assert.False(taskState.IsFinalState(), "TaskRunning should not be a final state."); Assert.True(taskState.MoveNext(TaskStateEvent.CompletedTask).Equals(TaskState.TaskCompleted), "Failed to move from TaskRunning to TaskCompleted state."); Assert.True(taskState.IsFinalState(), "TaskCompleted should be a final state."); }
public void TestFromRunningToNotAllowedTransitions() { var taskState = new TaskStateMachine(); taskState.MoveNext(TaskStateEvent.SubmittedTask); taskState.MoveNext(TaskStateEvent.RunningTask); Action moveNext = () => taskState.MoveNext(TaskStateEvent.SubmittedTask); Assert.Throws <TaskStateTransitionException>(moveNext); moveNext = () => taskState.MoveNext(TaskStateEvent.ClosedTask); Assert.Throws <TaskStateTransitionException>(moveNext); }
public static Task MainCompiled(string[] args) { var taskMethodBuilder = AsyncTaskMethodBuilder.Create(); TaskStateMachine stateMachine = new TaskStateMachine(); stateMachine.args = args; stateMachine.taskBuilder = taskMethodBuilder; stateMachine.state = -1; taskMethodBuilder.Start(ref stateMachine); return(stateMachine.taskBuilder.Task); }
// This is the section where actual logic of original method exist // Contain the logic to execute the code till await statement // Also configure stuff of the wake up call when async method complete it's execution public void MoveNext() { // Set state to local variable for performance int num = state; try { // Variables to save awaiters for the new tasks TaskAwaiter firstAwaiter; TaskAwaiter <bool> secondAwaiter; // Initially -1 if (num != 0) { if (num == 1) { // We get the awaiter from the execution context again secondAwaiter = SecondAwaiter; // Set to null to release memory allocation SecondAwaiter = default; // Restart the state as we are about to finish num = (state = -1); // Don't use goto unless you know what you are doing! :) goto IL_0114; } // Execute first task with its context inputContext = new InputContext(); inputContext.input = 5; firstAwaiter = Task.Run(inputContext.ConsoleWriteLine).GetAwaiter(); // This block is for optimization in case the task is already finished (Task.FromResult) // Most probably - this block will be executed if (!firstAwaiter.IsCompleted) { num = (state = 0); // Save the awaiter for the next state. FirstAwaiter = firstAwaiter; TaskStateMachine stateMachine = this; // This call to AwaitUnsafeOnCompleted is where most of the magic happens // In this step we register the StateMachine as continuation of the task by calling AwaitUnsafeOnCompleted // But how it is done? // builder.AwaitUnsafeOnCompleted do multiple things in background // 1. TaskMethodBuilder captures Execution context // 2. Create an MoveNextAction using Execution context // 3. This MoveNextAction will call the MoveNext of state machine and provide execution context // 4. Set MoveNextAction as callback to awaiter on complete Using awaiter.UnsafeOnCompleted(action) taskBuilder.AwaitUnsafeOnCompleted(ref firstAwaiter, ref stateMachine); return; } } else { // Second time - we get the awaiter from the execution context firstAwaiter = FirstAwaiter; // Set to null to release memory allocation FirstAwaiter = default; num = (state = -1); } firstAwaiter.GetResult(); // Execute second task with its context secondAwaiter = Task .Run(ReturnContext.FunctionCall ?? (ReturnContext.FunctionCall = ReturnContext.Context.ReturnTrue)) .GetAwaiter(); // Again - for optimization if (!secondAwaiter.IsCompleted) { num = (state = 1); // Save the awaiter for the next state. SecondAwaiter = secondAwaiter; TaskStateMachine stateMachine = this; // Register the state machine to continue with the next state taskBuilder.AwaitUnsafeOnCompleted(ref secondAwaiter, ref stateMachine); return; } IL_0114: // Finish by getting the awaiter result and execute the logic result = secondAwaiter.GetResult(); Console.WriteLine(result); } catch (Exception exception) { // Exception handling mechanism state = -2; taskBuilder.SetException(exception); return; } // Set the state to final state we are done state = -2; // Set the result on the task builder taskBuilder.SetResult(); }
/// <summary> /// Construct a TaskInfo that wraps task state, task configuration, and active context for submitting the task /// </summary> /// <param name="taskState"></param> /// <param name="config"></param> /// <param name="context"></param> internal TaskInfo(TaskStateMachine taskState, IConfiguration config, IActiveContext context) { _taskState = taskState; _taskConfiguration = config; _activeContext = context; }