How to use Complete method of Microsoft.Coyote.Runtime.Operation class

Best Coyote code snippet using Microsoft.Coyote.Runtime.Operation.Complete

CoyoteRuntime.cs

Source:CoyoteRuntime.cs Github

copy

Full Screen

...210 }211 if (testMethodTask != null)212 {213 // If the test method is asynchronous, then wait until it completes.214 op.TryBlockUntilTaskCompletes(testMethodTask);215 if (testMethodTask.Exception != null)216 {217 // The test method failed with an unhandled exception.218 ExceptionDispatchInfo.Capture(testMethodTask.Exception).Throw();219 }220 else if (testMethodTask.IsCanceled)221 {222 throw new TaskCanceledException(testMethodTask);223 }224 }225 IO.Debug.WriteLine("<ScheduleDebug> Completed operation {0} on task '{1}'.", op.Name, Task.CurrentId);226 op.OnCompleted();227 // Task has completed, schedule the next enabled operation, which terminates exploration.228 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Stop);229 }230 catch (Exception ex)231 {232 this.ProcessUnhandledExceptionInOperation(op, ex);233 }234 });235 task.Start();236 this.Scheduler.WaitOperationStart(op);237 }238 /// <summary>239 /// Creates a new task operation.240 /// </summary>241 internal TaskOperation CreateTaskOperation(bool isDelay = false)242 {243 ulong operationId = this.GetNextOperationId();244 TaskOperation op;245 if (isDelay)246 {247 op = new TaskDelayOperation(operationId, $"TaskDelay({operationId})", this.Configuration.TimeoutDelay,248 this.Scheduler);249 }250 else251 {252 op = new TaskOperation(operationId, $"Task({operationId})", this.Scheduler);253 }254 this.Scheduler.RegisterOperation(op);255 return op;256 }257 /// <summary>258 /// Schedules the specified action to be executed asynchronously.259 /// </summary>260#if !DEBUG261 [DebuggerStepThrough]262#endif263 internal Task ScheduleAction(Action action, Task predecessor, OperationExecutionOptions options,264 bool isDelay = false, CancellationToken cancellationToken = default)265 {266 cancellationToken.ThrowIfCancellationRequested();267 TaskOperation op = this.CreateTaskOperation(isDelay);268 var context = new OperationContext<Action, object>(op, action, predecessor, options, cancellationToken);269 var task = new Task(this.ExecuteOperation, context, cancellationToken);270 return this.ScheduleTaskOperation(op, task, context.ResultSource);271 }272 /// <summary>273 /// Schedules the specified function to be executed asynchronously.274 /// </summary>275#if !DEBUG276 [DebuggerStepThrough]277#endif278 internal Task<Task> ScheduleFunction(Func<Task> function, Task predecessor, CancellationToken cancellationToken)279 {280 cancellationToken.ThrowIfCancellationRequested();281 Task<Task> task = null;282 TaskOperation op = this.CreateTaskOperation();283 var context = new AsyncOperationContext<Func<Task>, Task, Task>(op, function, task, predecessor,284 OperationExecutionOptions.None, cancellationToken);285 task = new Task<Task>(this.ExecuteOperation<Func<Task>, Task, Task>, context, cancellationToken);286 return this.ScheduleTaskOperation(op, task, context.ExecutorSource);287 }288 /// <summary>289 /// Schedules the specified function to be executed asynchronously.290 /// </summary>291#if !DEBUG292 [DebuggerStepThrough]293#endif294 internal Task<Task<TResult>> ScheduleFunction<TResult>(Func<Task<TResult>> function, Task predecessor, CancellationToken cancellationToken)295 {296 cancellationToken.ThrowIfCancellationRequested();297 Task<TResult> task = null;298 TaskOperation op = this.CreateTaskOperation();299 var context = new AsyncOperationContext<Func<Task<TResult>>, Task<TResult>, TResult>(op, function, task, predecessor,300 OperationExecutionOptions.None, cancellationToken);301 task = new Task<TResult>(this.ExecuteOperation<Func<Task<TResult>>, Task<TResult>, TResult>, context, cancellationToken);302 return this.ScheduleTaskOperation(op, task, context.ExecutorSource);303 }304 /// <summary>305 /// Schedules the specified function to be executed asynchronously.306 /// </summary>307#if !DEBUG308 [DebuggerStepThrough]309#endif310 internal CoyoteTasks.Task ScheduleAsyncFunction(Func<CoyoteTasks.Task> function, Task predecessor, CancellationToken cancellationToken)311 {312 cancellationToken.ThrowIfCancellationRequested();313 Task<Task> task = null;314 TaskOperation op = this.CreateTaskOperation();315 var context = new AsyncOperationContext<Func<CoyoteTasks.Task>, Task, Task>(op, function, task, predecessor,316 OperationExecutionOptions.None, cancellationToken);317 task = new Task<Task>(this.ExecuteOperation<Func<CoyoteTasks.Task>, Task, Task>, context, cancellationToken);318 return new CoyoteTasks.Task(this, this.ScheduleTaskOperation(op, task, context.ResultSource));319 }320 /// <summary>321 /// Schedules the specified function to be executed asynchronously.322 /// </summary>323#if !DEBUG324 [DebuggerStepThrough]325#endif326 internal CoyoteTasks.Task<TResult> ScheduleAsyncFunction<TResult>(Func<CoyoteTasks.Task<TResult>> function, Task predecessor,327 CancellationToken cancellationToken)328 {329 cancellationToken.ThrowIfCancellationRequested();330 Task<TResult> task = null;331 TaskOperation op = this.CreateTaskOperation();332 var context = new AsyncOperationContext<Func<CoyoteTasks.Task<TResult>>, Task<TResult>, TResult>(op, function, task, predecessor,333 OperationExecutionOptions.None, cancellationToken);334 task = new Task<TResult>(this.ExecuteOperation<Func<CoyoteTasks.Task<TResult>>, Task<TResult>, TResult>, context, cancellationToken);335 return new CoyoteTasks.Task<TResult>(this, this.ScheduleTaskOperation(op, task, context.ResultSource));336 }337 /// <summary>338 /// Schedules the specified function to be executed asynchronously.339 /// </summary>340#if !DEBUG341 [DebuggerStepThrough]342#endif343 internal Task<TResult> ScheduleFunction<TResult>(Func<TResult> function, Task predecessor, CancellationToken cancellationToken)344 {345 cancellationToken.ThrowIfCancellationRequested();346 TaskOperation op = this.CreateTaskOperation();347 var context = new OperationContext<Func<TResult>, TResult>(op, function, predecessor,348 OperationExecutionOptions.None, cancellationToken);349 var task = new Task<TResult>(this.ExecuteOperation<Func<TResult>, TResult, TResult>, context, cancellationToken);350 return this.ScheduleTaskOperation(op, task, context.ResultSource);351 }352 /// <summary>353 /// Schedules the specified task operation for execution.354 /// </summary>355 private Task<TResult> ScheduleTaskOperation<TResult>(TaskOperation op, Task task, TaskCompletionSource<TResult> tcs)356 {357 IO.Debug.WriteLine("<CreateLog> Operation '{0}' was created to execute task '{1}'.", op.Name, task.Id);358 task.Start();359 this.Scheduler.WaitOperationStart(op);360 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Create);361 this.TaskMap.TryAdd(tcs.Task, op);362 return tcs.Task;363 }364 /// <summary>365 /// Execute the operation with the specified context.366 /// </summary>367 internal void ExecuteOperation(object state)368 {369 // Extract the expected operation context from the task state.370 var context = state as OperationContext<Action, object>;371 TaskOperation op = context.Operation;372 CancellationToken ct = context.CancellationToken;373 Exception exception = null;374 try375 {376 // Update the current asynchronous control flow with the current runtime instance,377 // allowing future retrieval in the same asynchronous call stack.378 AssignAsyncControlFlowRuntime(this);379 // Notify the scheduler that the operation started. This will yield execution until380 // the operation is ready to get scheduled.381 this.Scheduler.StartOperation(op);382 if (context.Predecessor != null)383 {384 // If the predecessor task is asynchronous, then wait until it completes.385 ct.ThrowIfCancellationRequested();386 op.TryBlockUntilTaskCompletes(context.Predecessor);387 }388 if (context.Options.HasFlag(OperationExecutionOptions.YieldAtStart))389 {390 // Try yield execution to the next operation.391 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Default, true);392 }393 if (op is TaskDelayOperation delayOp)394 {395 // Try delay scheduling this operation.396 delayOp.DelayUntilTimeout();397 }398 // Check if the operation must be canceled before starting the work.399 ct.ThrowIfCancellationRequested();400 // Start executing the work.401 context.Work();402 }403 catch (Exception ex)404 {405 if (context.Options.HasFlag(OperationExecutionOptions.FailOnException))406 {407 this.Assert(false, "Unhandled exception. {0}", ex);408 }409 else410 {411 // Unwrap and cache the exception to propagate it.412 exception = UnwrapException(ex);413 this.ReportThrownException(exception);414 }415 }416 finally417 {418 IO.Debug.WriteLine("<ScheduleDebug> Completed operation '{0}' on task '{1}'.", op.Name, Task.CurrentId);419 op.OnCompleted();420 // Set the result task completion source to notify to the awaiters that the operation421 // has been completed, and schedule the next enabled operation.422 SetTaskCompletionSource(context.ResultSource, null, exception, default);423 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Join);424 }425 }426 /// <summary>427 /// Execute the (asynchronous) operation with the specified context.428 /// </summary>429 private TResult ExecuteOperation<TWork, TExecutor, TResult>(object state)430 {431 // Extract the expected operation context from the task state.432 var context = state as AsyncOperationContext<TWork, TExecutor, TResult> ?? state as OperationContext<TWork, TResult>;433 TaskOperation op = context.Operation;434 CancellationToken ct = context.CancellationToken;435 TResult result = default;436 Exception exception = null;437 // The operation execution logic uses two task completion sources: (1) an executor TCS and (2) a result TCS.438 // We do this to model the execution of tasks in the .NET runtime. For example, the `Task.Factory.StartNew`439 // method has different semantics from `Task.Run`, e.g. the returned task from `Task.Factory.StartNew(Func<T>)`440 // completes at the start of an asynchronous operation, so someone cannot await on it for the completion of441 // the operation. Instead, someone needs to first use `task.Unwrap()`, and then await on the unwrapped task.442 // To model this, the executor TCS completes at the start of the operation, and contains in its `task.AsyncState`443 // a reference to the result TCS. This approach allows us to implement `task.Unwrap` in a way that gives access444 // to the result TCS, which someone can then await for the asynchronous completion of the operation.445 try446 {447 // Update the current asynchronous control flow with the current runtime instance,448 // allowing future retrieval in the same asynchronous call stack.449 AssignAsyncControlFlowRuntime(this);450 // Notify the scheduler that the operation started. This will yield execution until451 // the operation is ready to get scheduled.452 this.Scheduler.StartOperation(op);453 if (context is AsyncOperationContext<TWork, TExecutor, TResult> asyncContext)454 {455 // If the operation is asynchronous, then set the executor task completion source, which456 // can be used by `UnwrapTask` to unwrap and return the task executing this operation.457 SetTaskCompletionSource(asyncContext.ExecutorSource, asyncContext.Executor, null, ct);458 }459 if (context.Predecessor != null)460 {461 // If the predecessor task is asynchronous, then wait until it completes.462 ct.ThrowIfCancellationRequested();463 op.TryBlockUntilTaskCompletes(context.Predecessor);464 }465 // Check if the operation must be canceled before starting the work.466 ct.ThrowIfCancellationRequested();467 // Start executing the (asynchronous) work.468 Task executor = null;469 if (context.Work is Func<Task<TResult>> funcWithTaskResult)470 {471 executor = funcWithTaskResult();472 }473 else if (context.Work is Func<Task> funcWithTask)474 {475 executor = funcWithTask();476 }477 else if (context.Work is Func<CoyoteTasks.Task<TResult>> funcWithCoyoteTaskResult)478 {479 // TODO: temporary until we remove the custom task type.480 executor = funcWithCoyoteTaskResult().UncontrolledTask;481 }482 else if (context.Work is Func<CoyoteTasks.Task> funcWithCoyoteTask)483 {484 // TODO: temporary until we remove the custom task type.485 executor = funcWithCoyoteTask().UncontrolledTask;486 }487 else if (context.Work is Func<TResult> func)488 {489 result = func();490 }491 else492 {493 throw new NotSupportedException($"Unable to execute work with unsupported type {context.Work.GetType()}.");494 }495 if (executor != null)496 {497 // If the work task is asynchronous, then wait until it completes.498 op.TryBlockUntilTaskCompletes(executor);499 if (executor.IsFaulted)500 {501 // Propagate the failing exception by rethrowing it.502 ExceptionDispatchInfo.Capture(executor.Exception).Throw();503 }504 else if (executor.IsCanceled)505 {506 if (op.Exception != null)507 {508 // An exception has been already captured, so propagate it.509 ExceptionDispatchInfo.Capture(op.Exception).Throw();510 }511 else512 {513 // Wait the canceled executor (which is non-blocking as it has already completed)514 // to throw the generated `OperationCanceledException`.515 executor.Wait();516 }517 }518 // Safely get the result without blocking as the work has completed.519 result = executor is Task<TResult> resultTask ? resultTask.Result :520 executor is TResult r ? r : default;521 }522 }523 catch (Exception ex)524 {525 // Unwrap and cache the exception to propagate it.526 exception = UnwrapException(ex);527 this.ReportThrownException(exception);528 }529 finally530 {531 IO.Debug.WriteLine("<ScheduleDebug> Completed operation '{0}' on task '{1}'.", op.Name, Task.CurrentId);532 op.OnCompleted();533 // Set the result task completion source to notify to the awaiters that the operation534 // has been completed, and schedule the next enabled operation.535 SetTaskCompletionSource(context.ResultSource, result, exception, default);536 this.Scheduler.ScheduleNextOperation(AsyncOperationType.Join);537 }538 return result;539 }540 /// <summary>541 /// Sets the specified task completion source with a result, cancelation or exception.542 /// </summary>543 private static void SetTaskCompletionSource<TResult>(TaskCompletionSource<TResult> tcs, TResult result,544 Exception ex, CancellationToken cancellationToken)545 {546 if (cancellationToken.IsCancellationRequested)547 {548 tcs.SetCanceled();549 }550 else if (ex != null)551 {552 tcs.SetException(ex);553 }554 else555 {556 tcs.SetResult(result);557 }558 }559 /// <summary>560 /// Schedules the specified delay to be executed asynchronously.561 /// </summary>562#if !DEBUG563 [DebuggerStepThrough]564#endif565 internal Task ScheduleDelay(TimeSpan delay, CancellationToken cancellationToken)566 {567 // TODO: support cancellations during testing.568 if (delay.TotalMilliseconds is 0)569 {570 // If the delay is 0, then complete synchronously.571 return Task.CompletedTask;572 }573 // TODO: cache the dummy delay action to optimize memory.574 var options = OperationContext.CreateOperationExecutionOptions();575 return this.ScheduleAction(() => { }, null, options, true, cancellationToken);576 }577 /// <summary>578 /// Schedules the specified task awaiter continuation to be executed asynchronously.579 /// </summary>580#if !DEBUG581 [DebuggerStepThrough]582#endif583 internal void ScheduleTaskAwaiterContinuation(Task task, Action continuation)584 {585 try586 {587 var callerOp = this.Scheduler?.GetExecutingOperation<TaskOperation>();588 if (callerOp is null)589 {590 OperationScheduler.ThrowUncontrolledTaskException();591 }592 if (IsCurrentOperationExecutingAsynchronously())593 {594 IO.Debug.WriteLine("<Task> '{0}' is dispatching continuation of task '{1}'.", callerOp.Name, task.Id);595 var options = OperationContext.CreateOperationExecutionOptions();596 this.ScheduleAction(continuation, task, options);597 IO.Debug.WriteLine("<Task> '{0}' dispatched continuation of task '{1}'.", callerOp.Name, task.Id);598 }599 else600 {601 IO.Debug.WriteLine("<Task> '{0}' is executing continuation of task '{1}' on task '{2}'.",602 callerOp.Name, task.Id, Task.CurrentId);603 continuation();604 IO.Debug.WriteLine("<Task> '{0}' resumed after continuation of task '{1}' on task '{2}'.",605 callerOp.Name, task.Id, Task.CurrentId);606 }607 }608 catch (ExecutionCanceledException)609 {610 IO.Debug.WriteLine($"<Exception> ExecutionCanceledException was thrown from task '{Task.CurrentId}'.");611 }612 }613 /// <summary>614 /// Schedules the specified yield awaiter continuation to be executed asynchronously.615 /// </summary>616#if !DEBUG617 [DebuggerStepThrough]618#endif619 internal void ScheduleYieldAwaiterContinuation(Action continuation)620 {621 try622 {623 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();624 IO.Debug.WriteLine("<Task> '{0}' is executing a yield operation.", callerOp.Id);625 var options = OperationContext.CreateOperationExecutionOptions(yieldAtStart: true);626 this.ScheduleAction(continuation, null, options);627 }628 catch (ExecutionCanceledException)629 {630 IO.Debug.WriteLine($"<Exception> ExecutionCanceledException was thrown from task '{Task.CurrentId}'.");631 }632 }633 /// <summary>634 /// Creates a controlled task that will complete when all tasks635 /// in the specified enumerable collection have completed.636 /// </summary>637#if !DEBUG638 [DebuggerStepThrough]639#endif640 internal Task WhenAllTasksCompleteAsync(Task[] tasks)641 {642 if (tasks is null)643 {644 throw new ArgumentNullException(nameof(tasks));645 }646 else if (tasks.Length is 0)647 {648 return Task.CompletedTask;649 }650 return this.ScheduleAction(() =>651 {652 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();653 callerOp.BlockUntilTasksComplete(tasks, waitAll: true);654 List<Exception> exceptions = null;655 foreach (var task in tasks)656 {657 if (task.IsFaulted)658 {659 exceptions ??= new List<Exception>();660 exceptions.Add(task.Exception is AggregateException aex ? aex.InnerException : task.Exception);661 }662 }663 if (exceptions != null)664 {665 throw new AggregateException(exceptions);666 }667 }, null, OperationContext.CreateOperationExecutionOptions());668 }669 /// <summary>670 /// Creates a controlled task that will complete when all tasks671 /// in the specified enumerable collection have completed.672 /// </summary>673#if !DEBUG674 [DebuggerStepThrough]675#endif676 internal Task WhenAllTasksCompleteAsync(CoyoteTasks.Task[] tasks)677 {678 if (tasks is null)679 {680 throw new ArgumentNullException(nameof(tasks));681 }682 else if (tasks.Length is 0)683 {684 return Task.CompletedTask;685 }686 return this.ScheduleAction(() =>687 {688 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();689 callerOp.BlockUntilTasksComplete(tasks, waitAll: true);690 List<Exception> exceptions = null;691 foreach (var task in tasks)692 {693 if (task.IsFaulted)694 {695 exceptions ??= new List<Exception>();696 exceptions.Add(task.Exception is AggregateException aex ? aex.InnerException : task.Exception);697 }698 }699 if (exceptions != null)700 {701 throw new AggregateException(exceptions);702 }703 }, null, OperationContext.CreateOperationExecutionOptions());704 }705 /// <summary>706 /// Creates a controlled task that will complete when all tasks707 /// in the specified enumerable collection have completed.708 /// </summary>709#if !DEBUG710 [DebuggerStepThrough]711#endif712 internal Task<TResult[]> WhenAllTasksCompleteAsync<TResult>(Task<TResult>[] tasks)713 {714 if (tasks is null)715 {716 throw new ArgumentNullException(nameof(tasks));717 }718 else if (tasks.Length is 0)719 {720 return Task.FromResult(Array.Empty<TResult>());721 }722 return this.ScheduleFunction(() =>723 {724 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();725 callerOp.BlockUntilTasksComplete(tasks, waitAll: true);726 List<Exception> exceptions = null;727 foreach (var task in tasks)728 {729 if (task.IsFaulted)730 {731 exceptions ??= new List<Exception>();732 exceptions.Add(task.Exception is AggregateException aex ? aex.InnerException : task.Exception);733 }734 }735 if (exceptions != null)736 {737 throw new AggregateException(exceptions);738 }739 int idx = 0;740 TResult[] result = new TResult[tasks.Length];741 foreach (var task in tasks)742 {743 result[idx] = task.Result;744 idx++;745 }746 return result;747 }, null, default);748 }749 /// <summary>750 /// Creates a controlled task that will complete when all tasks751 /// in the specified enumerable collection have completed.752 /// </summary>753#if !DEBUG754 [DebuggerStepThrough]755#endif756 internal Task<TResult[]> WhenAllTasksCompleteAsync<TResult>(CoyoteTasks.Task<TResult>[] tasks)757 {758 if (tasks is null)759 {760 throw new ArgumentNullException(nameof(tasks));761 }762 else if (tasks.Length is 0)763 {764 return Task.FromResult(Array.Empty<TResult>());765 }766 return this.ScheduleFunction(() =>767 {768 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();769 callerOp.BlockUntilTasksComplete(tasks, waitAll: true);770 List<Exception> exceptions = null;771 foreach (var task in tasks)772 {773 if (task.IsFaulted)774 {775 exceptions ??= new List<Exception>();776 exceptions.Add(task.Exception is AggregateException aex ? aex.InnerException : task.Exception);777 }778 }779 if (exceptions != null)780 {781 throw new AggregateException(exceptions);782 }783 int idx = 0;784 TResult[] result = new TResult[tasks.Length];785 foreach (var task in tasks)786 {787 result[idx] = task.Result;788 idx++;789 }790 return result;791 }, null, default);792 }793 /// <summary>794 /// Creates a controlled task that will complete when any task795 /// in the specified enumerable collection have completed.796 /// </summary>797#if !DEBUG798 [DebuggerStepThrough]799#endif800 internal Task<Task> WhenAnyTaskCompletesAsync(Task[] tasks)801 {802 if (tasks is null)803 {804 throw new ArgumentNullException(nameof(tasks));805 }806 else if (tasks.Length is 0)807 {808 throw new ArgumentException("The tasks argument contains no tasks.");809 }810 var task = this.ScheduleFunction(() =>811 {812 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();813 callerOp.BlockUntilTasksComplete(tasks, waitAll: false);814 Task result = null;815 foreach (var task in tasks)816 {817 if (task.IsCompleted)818 {819 result = task;820 break;821 }822 }823 return Task.FromResult(result);824 }, null, default);825 return this.UnwrapTask(task);826 }827 /// <summary>828 /// Creates a controlled task that will complete when any task829 /// in the specified enumerable collection have completed.830 /// </summary>831#if !DEBUG832 [DebuggerStepThrough]833#endif834 internal CoyoteTasks.Task<CoyoteTasks.Task> WhenAnyTaskCompletesAsync(CoyoteTasks.Task[] tasks)835 {836 if (tasks is null)837 {838 throw new ArgumentNullException(nameof(tasks));839 }840 else if (tasks.Length is 0)841 {842 throw new ArgumentException("The tasks argument contains no tasks.");843 }844 return this.ScheduleAsyncFunction(() =>845 {846 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();847 callerOp.BlockUntilTasksComplete(tasks, waitAll: false);848 CoyoteTasks.Task result = null;849 foreach (var task in tasks)850 {851 if (task.IsCompleted)852 {853 result = task;854 break;855 }856 }857 return CoyoteTasks.Task.FromResult(result);858 }, null, default);859 }860 /// <summary>861 /// Creates a controlled task that will complete when any task862 /// in the specified enumerable collection have completed.863 /// </summary>864#if !DEBUG865 [DebuggerStepThrough]866#endif867 internal Task<Task<TResult>> WhenAnyTaskCompletesAsync<TResult>(Task<TResult>[] tasks)868 {869 if (tasks is null)870 {871 throw new ArgumentNullException(nameof(tasks));872 }873 else if (tasks.Length is 0)874 {875 throw new ArgumentException("The tasks argument contains no tasks.");876 }877 var task = this.ScheduleFunction(() =>878 {879 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();880 callerOp.BlockUntilTasksComplete(tasks, waitAll: false);881 Task<TResult> result = null;882 foreach (var task in tasks)883 {884 if (task.IsCompleted)885 {886 result = task;887 break;888 }889 }890 return Task.FromResult(result);891 }, null, default);892 return this.UnwrapTask(task);893 }894 /// <summary>895 /// Creates a controlled task that will complete when any task896 /// in the specified enumerable collection have completed.897 /// </summary>898#if !DEBUG899 [DebuggerStepThrough]900#endif901 internal CoyoteTasks.Task<CoyoteTasks.Task<TResult>> WhenAnyTaskCompletesAsync<TResult>(CoyoteTasks.Task<TResult>[] tasks)902 {903 if (tasks is null)904 {905 throw new ArgumentNullException(nameof(tasks));906 }907 else if (tasks.Length is 0)908 {909 throw new ArgumentException("The tasks argument contains no tasks.");910 }911 return this.ScheduleAsyncFunction(() =>912 {913 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();914 callerOp.BlockUntilTasksComplete(tasks, waitAll: false);915 CoyoteTasks.Task<TResult> result = null;916 foreach (var task in tasks)917 {918 if (task.IsCompleted)919 {920 result = task;921 break;922 }923 }924 return CoyoteTasks.Task.FromResult(result);925 }, null, default);926 }927 /// <summary>928 /// Waits for all of the provided controlled task objects to complete execution within929 /// a specified number of milliseconds or until a cancellation token is cancelled.930 /// </summary>931 internal bool WaitAllTasksComplete(Task[] tasks)932 {933 // TODO: support cancellations during testing.934 if (tasks is null)935 {936 throw new ArgumentNullException(nameof(tasks));937 }938 else if (tasks.Length is 0)939 {940 return true;941 }942 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();943 callerOp.BlockUntilTasksComplete(tasks, waitAll: true);944 // TODO: support timeouts during testing, this would become false if there is a timeout.945 return true;946 }947 /// <summary>948 /// Waits for all of the provided controlled task objects to complete execution within949 /// a specified number of milliseconds or until a cancellation token is cancelled.950 /// </summary>951 internal bool WaitAllTasksComplete(CoyoteTasks.Task[] tasks)952 {953 // TODO: support cancellations during testing.954 if (tasks is null)955 {956 throw new ArgumentNullException(nameof(tasks));957 }958 else if (tasks.Length is 0)959 {960 return true;961 }962 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();963 callerOp.BlockUntilTasksComplete(tasks, waitAll: true);964 // TODO: support timeouts during testing, this would become false if there is a timeout.965 return true;966 }967 /// <summary>968 /// Waits for any of the provided controlled task objects to complete execution within969 /// a specified number of milliseconds or until a cancellation token is cancelled.970 /// </summary>971#if !DEBUG972 [DebuggerStepThrough]973#endif974 internal int WaitAnyTaskCompletes(Task[] tasks)975 {976 // TODO: support cancellations during testing.977 if (tasks is null)978 {979 throw new ArgumentNullException(nameof(tasks));980 }981 else if (tasks.Length is 0)982 {983 throw new ArgumentException("The tasks argument contains no tasks.");984 }985 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();986 callerOp.BlockUntilTasksComplete(tasks, waitAll: false);987 int result = -1;988 for (int i = 0; i < tasks.Length; i++)989 {990 if (tasks[i].IsCompleted)991 {992 result = i;993 break;994 }995 }996 // TODO: support timeouts during testing, this would become false if there is a timeout.997 return result;998 }999 /// <summary>1000 /// Waits for any of the provided controlled task objects to complete execution within1001 /// a specified number of milliseconds or until a cancellation token is cancelled.1002 /// </summary>1003#if !DEBUG1004 [DebuggerStepThrough]1005#endif1006 internal int WaitAnyTaskCompletes(CoyoteTasks.Task[] tasks)1007 {1008 // TODO: support cancellations during testing.1009 if (tasks is null)1010 {1011 throw new ArgumentNullException(nameof(tasks));1012 }1013 else if (tasks.Length is 0)1014 {1015 throw new ArgumentException("The tasks argument contains no tasks.");1016 }1017 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();1018 callerOp.BlockUntilTasksComplete(tasks, waitAll: false);1019 int result = -1;1020 for (int i = 0; i < tasks.Length; i++)1021 {1022 if (tasks[i].IsCompleted)1023 {1024 result = i;1025 break;1026 }1027 }1028 // TODO: support timeouts during testing, this would become false if there is a timeout.1029 return result;1030 }1031 /// <summary>1032 /// Waits for the task to complete execution. The wait terminates if a timeout interval1033 /// elapses or a cancellation token is canceled before the task completes.1034 /// </summary>1035 internal bool WaitTaskCompletes(Task task)1036 {1037 this.AssertIsAwaitedTaskControlled(task);1038 // TODO: support timeouts and cancellation tokens.1039 if (!task.IsCompleted)1040 {1041 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();1042 callerOp.BlockUntilTaskCompletes(task);1043 }1044 if (task.IsFaulted)1045 {1046 // Propagate the failing exception by rethrowing it.1047 ExceptionDispatchInfo.Capture(task.Exception).Throw();1048 }1049 return true;1050 }1051 /// <summary>1052 /// Waits for the task to complete execution and returns the result.1053 /// </summary>1054 internal TResult WaitTaskCompletes<TResult>(Task<TResult> task)1055 {1056 this.AssertIsAwaitedTaskControlled(task);1057 // TODO: support timeouts and cancellation tokens.1058 if (!task.IsCompleted)1059 {1060 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();1061 callerOp.BlockUntilTaskCompletes(task);1062 }1063 if (task.IsFaulted)1064 {1065 // Propagate the failing exception by rethrowing it.1066 ExceptionDispatchInfo.Capture(task.Exception).Throw();1067 }1068 return task.Result;1069 }1070 /// <summary>1071 /// Unwraps the specified task.1072 /// </summary>1073 internal Task UnwrapTask(Task<Task> task)1074 {1075 var unwrappedTask = task.AsyncState is TaskCompletionSource<Task> tcs ? tcs.Task : task.Unwrap();1076 this.TaskMap.TryGetValue(task, out TaskOperation op);1077 this.TaskMap.TryAdd(unwrappedTask, op);1078 return unwrappedTask;1079 }1080 /// <summary>1081 /// Unwraps the specified task.1082 /// </summary>1083 internal Task<TResult> UnwrapTask<TResult>(Task<Task<TResult>> task)1084 {1085 var unwrappedTask = task.AsyncState is TaskCompletionSource<TResult> tcs ? tcs.Task : task.Unwrap();1086 this.TaskMap.TryGetValue(task, out TaskOperation op);1087 this.TaskMap.TryAdd(unwrappedTask, op);1088 return unwrappedTask;1089 }1090 /// <summary>1091 /// Callback invoked when the task of a task completion source is accessed.1092 /// </summary>1093 internal void OnTaskCompletionSourceGetTask(Task task)1094 {1095 this.TaskMap.TryAdd(task, null);1096 }1097 /// <summary>1098 /// Callback invoked when the <see cref="AsyncTaskMethodBuilder.SetException"/> is accessed.1099 /// </summary>1100 internal void OnAsyncTaskMethodBuilderSetException(Exception exception)1101 {1102 var op = this.Scheduler.GetExecutingOperation<TaskOperation>();1103 op?.SetException(exception);1104 }1105 /// <summary>1106 /// Checks if the currently executing operation is controlled by the runtime.1107 /// </summary>1108#if !DEBUG1109 [DebuggerHidden]1110#endif1111 internal void CheckExecutingOperationIsControlled() =>1112 this.Scheduler.GetExecutingOperation<AsyncOperation>();1113 /// <summary>1114 /// Callback invoked when the <see cref="CoyoteTasks.YieldAwaitable.YieldAwaiter.GetResult"/> is called.1115 /// </summary>1116#if !DEBUG1117 [DebuggerStepThrough]1118#endif1119 internal void OnYieldAwaiterGetResult() => this.Scheduler.ScheduleNextOperation(AsyncOperationType.Yield);1120 /// <summary>1121 /// Callback invoked when the executing operation is waiting for the specified task to complete.1122 /// </summary>1123#if !DEBUG1124 [DebuggerStepThrough]1125#endif1126 internal void OnWaitTask(Task task)1127 {1128 if (!task.IsCompleted)1129 {1130 var callerOp = this.Scheduler.GetExecutingOperation<TaskOperation>();1131 callerOp.BlockUntilTaskCompletes(task);1132 }1133 }1134 /// <summary>1135 /// Returns true if the current operation is executing an asynchronous state machine, else false.1136 /// </summary>1137 private static bool IsCurrentOperationExecutingAsynchronously()1138 {1139 StackTrace st = new StackTrace(false);1140 bool result = false;1141 for (int i = 0; i < st.FrameCount; i++)1142 {1143 // Traverse the stack trace to find if the current operation is executing an asynchronous state machine.1144 MethodBase method = st.GetFrame(i).GetMethod();1145 if (method.DeclaringType == typeof(AsyncVoidMethodBuilder) &&1146 (method.Name is "AwaitOnCompleted" || method.Name is "AwaitUnsafeOnCompleted"))1147 {1148 // The operation is executing the root of an async void method, so we need to inline.1149 break;1150 }1151 else if (method.Name is "MoveNext" &&1152 method.DeclaringType.Namespace != typeof(OperationScheduler).Namespace &&1153 typeof(IAsyncStateMachine).IsAssignableFrom(method.DeclaringType))1154 {1155 // The operation is executing the `MoveNext` of an asynchronous state machine.1156 result = true;1157 break;1158 }1159 }1160 return result;1161 }1162 /// <summary>1163 /// Processes an unhandled exception in the specified asynchronous operation.1164 /// </summary>1165 private void ProcessUnhandledExceptionInOperation(AsyncOperation op, Exception ex)1166 {1167 string message = null;1168 Exception exception = UnwrapException(ex);1169 if (exception is ExecutionCanceledException ece)1170 {1171 IO.Debug.WriteLine("<Exception> {0} was thrown from operation '{1}'.",1172 ece.GetType().Name, op.Name);1173 if (this.Scheduler.IsAttached)1174 {1175 // TODO: add some tests for this, so that we check that a task (or lock) that1176 // was cached and reused from prior iteration indeed cannot cause the runtime1177 // to hang anymore.1178 message = string.Format(CultureInfo.InvariantCulture, $"Unhandled exception. {ece}");1179 }1180 }1181 else if (exception is TaskSchedulerException)1182 {1183 IO.Debug.WriteLine("<Exception> {0} was thrown from operation '{1}'.",1184 exception.GetType().Name, op.Name);1185 }1186 else if (exception is ObjectDisposedException)1187 {1188 IO.Debug.WriteLine("<Exception> {0} was thrown from operation '{1}' with reason '{2}'.",1189 exception.GetType().Name, op.Name, ex.Message);1190 }1191 else1192 {1193 message = string.Format(CultureInfo.InvariantCulture, $"Unhandled exception. {exception}");1194 }1195 if (message != null)1196 {1197 // Report the unhandled exception.1198 this.Scheduler.NotifyUnhandledException(exception, message);1199 }1200 }1201 /// <summary>1202 /// Unwraps the specified exception.1203 /// </summary>1204 private static Exception UnwrapException(Exception ex)1205 {1206 Exception exception = ex;1207 while (exception is TargetInvocationException)1208 {1209 exception = exception.InnerException;1210 }1211 if (exception is AggregateException)1212 {1213 exception = exception.InnerException;1214 }1215 return exception;1216 }1217 /// <summary>1218 /// Registers a new specification monitor of the specified <see cref="Type"/>.1219 /// </summary>1220 internal void RegisterMonitor<T>()1221 where T : Monitor => this.DefaultActorExecutionContext.RegisterMonitor<T>();1222 /// <summary>1223 /// Invokes the specified monitor with the specified <see cref="Event"/>.1224 /// </summary>1225 internal void Monitor<T>(Event e)1226 where T : Monitor => this.DefaultActorExecutionContext.Monitor<T>(e);1227 /// <summary>1228 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.1229 /// </summary>1230 internal void Assert(bool predicate) => this.SpecificationEngine.Assert(predicate);1231 /// <summary>1232 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.1233 /// </summary>1234 internal void Assert(bool predicate, string s, object arg0) => this.SpecificationEngine.Assert(predicate, s, arg0);1235 /// <summary>1236 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.1237 /// </summary>1238 internal void Assert(bool predicate, string s, object arg0, object arg1) =>1239 this.SpecificationEngine.Assert(predicate, s, arg0, arg1);1240 /// <summary>1241 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.1242 /// </summary>1243 internal void Assert(bool predicate, string s, object arg0, object arg1, object arg2) =>1244 this.SpecificationEngine.Assert(predicate, s, arg0, arg1, arg2);1245 /// <summary>1246 /// Checks if the assertion holds, and if not, throws an <see cref="AssertionFailureException"/> exception.1247 /// </summary>1248 internal void Assert(bool predicate, string s, params object[] args) => this.SpecificationEngine.Assert(predicate, s, args);1249 /// <summary>1250 /// Creates a liveness monitor that checks if the specified task eventually completes execution successfully.1251 /// </summary>1252#if !DEBUG1253 [DebuggerStepThrough]1254#endif1255 internal void MonitorTaskCompletion(Task task) => this.SpecificationEngine.MonitorTaskCompletion(task);1256#if !DEBUG1257 [DebuggerStepThrough]1258#endif1259 internal void AssertIsAwaitedTaskControlled(Task task)1260 {1261 if (!task.IsCompleted && !this.TaskMap.ContainsKey(task) &&1262 !this.Configuration.IsPartiallyControlledTestingEnabled)1263 {1264 this.Assert(false, $"Awaiting uncontrolled task with id '{task.Id}' is not allowed: " +1265 "either mock the method that created the task, or rewrite the method's assembly.");1266 }1267 }1268#if !DEBUG1269 [DebuggerStepThrough]1270#endif1271 internal void AssertIsReturnedTaskControlled(Task task, string methodName)1272 {1273 if (!task.IsCompleted && !this.TaskMap.ContainsKey(task) &&1274 !this.Configuration.IsPartiallyControlledTestingEnabled)1275 {1276 this.Assert(false, $"Method '{methodName}' returned an uncontrolled task with id '{task.Id}', " +1277 "which is not allowed: either mock the method, or rewrite the method's assembly.");1278 }1279 }1280 /// <summary>1281 /// Returns a controlled nondeterministic boolean choice.1282 /// </summary>1283 internal bool GetNondeterministicBooleanChoice(int maxValue, string callerName, string callerType) =>1284 this.DefaultActorExecutionContext.GetNondeterministicBooleanChoice(maxValue, callerName, callerType);1285 /// <summary>1286 /// Returns a controlled nondeterministic integer choice.1287 /// </summary>...

Full Screen

Full Screen

ControlledTask.cs

Source:ControlledTask.cs Github

copy

Full Screen

...128 /// in the specified array have completed.129 /// </summary>130 [MethodImpl(MethodImplOptions.AggressiveInlining)]131 public static Task WhenAll(params Task[] tasks) => CoyoteRuntime.IsExecutionControlled ?132 CoyoteRuntime.Current.WhenAllTasksCompleteAsync(tasks) : Task.WhenAll(tasks);133 /// <summary>134 /// Creates a <see cref="Task"/> that will complete when all tasks135 /// in the specified enumerable collection have completed.136 /// </summary>137 [MethodImpl(MethodImplOptions.AggressiveInlining)]138 public static Task WhenAll(IEnumerable<Task> tasks) => CoyoteRuntime.IsExecutionControlled ?139 CoyoteRuntime.Current.WhenAllTasksCompleteAsync(tasks.ToArray()) : Task.WhenAll(tasks);140 /// <summary>141 /// Creates a <see cref="Task"/> that will complete when all tasks142 /// in the specified array have completed.143 /// </summary>144 [MethodImpl(MethodImplOptions.AggressiveInlining)]145 public static Task<TResult[]> WhenAll<TResult>(params Task<TResult>[] tasks) => CoyoteRuntime.IsExecutionControlled ?146 CoyoteRuntime.Current.WhenAllTasksCompleteAsync(tasks) : Task.WhenAll(tasks);147 /// <summary>148 /// Creates a <see cref="Task"/> that will complete when all tasks149 /// in the specified enumerable collection have completed.150 /// </summary>151 [MethodImpl(MethodImplOptions.AggressiveInlining)]152 public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks) => CoyoteRuntime.IsExecutionControlled ?153 CoyoteRuntime.Current.WhenAllTasksCompleteAsync(tasks.ToArray()) : Task.WhenAll(tasks);154 /// <summary>155 /// Creates a <see cref="Task"/> that will complete when any task156 /// in the specified array have completed.157 /// </summary>158 [MethodImpl(MethodImplOptions.AggressiveInlining)]159 public static Task<Task> WhenAny(params Task[] tasks) => CoyoteRuntime.IsExecutionControlled ?160 CoyoteRuntime.Current.WhenAnyTaskCompletesAsync(tasks) : Task.WhenAny(tasks);161 /// <summary>162 /// Creates a <see cref="Task"/> that will complete when any task163 /// in the specified enumerable collection have completed.164 /// </summary>165 [MethodImpl(MethodImplOptions.AggressiveInlining)]166 public static Task<Task> WhenAny(IEnumerable<Task> tasks) => CoyoteRuntime.IsExecutionControlled ?167 CoyoteRuntime.Current.WhenAnyTaskCompletesAsync(tasks.ToArray()) : Task.WhenAny(tasks);168#if NET5_0169 /// <summary>170 /// Creates a <see cref="Task"/> that will complete when either of the171 /// two tasks have completed.172 /// </summary>173 [MethodImpl(MethodImplOptions.AggressiveInlining)]174 public static Task<Task> WhenAny(Task t1, Task t2) => CoyoteRuntime.IsExecutionControlled ?175 CoyoteRuntime.Current.WhenAnyTaskCompletesAsync(new Task[] { t1, t2 }) : Task.WhenAny(t1, t2);176 /// <summary>177 /// Creates a <see cref="Task"/> that will complete when either of the178 /// two tasks have completed.179 /// </summary>180 [MethodImpl(MethodImplOptions.AggressiveInlining)]181 public static Task<Task<TResult>> WhenAny<TResult>(Task<TResult> t1, Task<TResult> t2) => CoyoteRuntime.IsExecutionControlled ?182 CoyoteRuntime.Current.WhenAnyTaskCompletesAsync(new Task<TResult>[] { t1, t2 }) : Task.WhenAny(t1, t2);183#endif184 /// <summary>185 /// Creates a <see cref="Task"/> that will complete when any task186 /// in the specified array have completed.187 /// </summary>188 [MethodImpl(MethodImplOptions.AggressiveInlining)]189 public static Task<Task<TResult>> WhenAny<TResult>(params Task<TResult>[] tasks) => CoyoteRuntime.IsExecutionControlled ?190 CoyoteRuntime.Current.WhenAnyTaskCompletesAsync(tasks) : Task.WhenAny(tasks);191 /// <summary>192 /// Creates a <see cref="Task"/> that will complete when any task193 /// in the specified enumerable collection have completed.194 /// </summary>195 [MethodImpl(MethodImplOptions.AggressiveInlining)]196 public static Task<Task<TResult>> WhenAny<TResult>(IEnumerable<Task<TResult>> tasks) => CoyoteRuntime.IsExecutionControlled ?197 CoyoteRuntime.Current.WhenAnyTaskCompletesAsync(tasks.ToArray()) : Task.WhenAny(tasks);198 /// <summary>199 /// Waits for all of the provided <see cref="Task"/> objects to complete execution.200 /// </summary>201 [MethodImpl(MethodImplOptions.AggressiveInlining)]202 public static void WaitAll(params Task[] tasks) => WaitAll(tasks, Timeout.Infinite, default);203 /// <summary>204 /// Waits for all of the provided <see cref="Task"/> objects to complete205 /// execution within a specified time interval.206 /// </summary>207 [MethodImpl(MethodImplOptions.AggressiveInlining)]208 public static bool WaitAll(Task[] tasks, TimeSpan timeout)209 {210 long totalMilliseconds = (long)timeout.TotalMilliseconds;211 if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)212 {213 throw new ArgumentOutOfRangeException(nameof(timeout));214 }215 return WaitAll(tasks, (int)totalMilliseconds, default);216 }217 /// <summary>218 /// Waits for all of the provided <see cref="Task"/> objects to complete219 /// execution within a specified number of milliseconds.220 /// </summary>221 [MethodImpl(MethodImplOptions.AggressiveInlining)]222 public static bool WaitAll(Task[] tasks, int millisecondsTimeout) => WaitAll(tasks, millisecondsTimeout, default);223 /// <summary>224 /// Waits for all of the provided <see cref="Task"/> objects to complete225 /// execution unless the wait is cancelled.226 /// </summary>227 [MethodImpl(MethodImplOptions.AggressiveInlining)]228 public static void WaitAll(Task[] tasks, CancellationToken cancellationToken) =>229 WaitAll(tasks, Timeout.Infinite, cancellationToken);230 /// <summary>231 /// Waits for any of the provided <see cref="Task"/> objects to complete232 /// execution within a specified number of milliseconds or until a cancellation233 /// token is cancelled.234 /// </summary>235 [MethodImpl(MethodImplOptions.AggressiveInlining)]236 public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) =>237 CoyoteRuntime.IsExecutionControlled ?238 CoyoteRuntime.Current.WaitAllTasksComplete(tasks) :239 Task.WaitAll(tasks, millisecondsTimeout, cancellationToken);240 /// <summary>241 /// Waits for any of the provided <see cref="Task"/> objects to complete execution.242 /// </summary>243 [MethodImpl(MethodImplOptions.AggressiveInlining)]244 public static int WaitAny(params Task[] tasks) => WaitAny(tasks, Timeout.Infinite, default);245 /// <summary>246 /// Waits for any of the provided <see cref="Task"/> objects to complete247 /// execution within a specified time interval.248 /// </summary>249 [MethodImpl(MethodImplOptions.AggressiveInlining)]250 public static int WaitAny(Task[] tasks, TimeSpan timeout)251 {252 long totalMilliseconds = (long)timeout.TotalMilliseconds;253 if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)254 {255 throw new ArgumentOutOfRangeException(nameof(timeout));256 }257 return WaitAny(tasks, (int)totalMilliseconds, default);258 }259 /// <summary>260 /// Waits for any of the provided <see cref="Task"/> objects to complete261 /// execution within a specified number of milliseconds.262 /// </summary>263 [MethodImpl(MethodImplOptions.AggressiveInlining)]264 public static int WaitAny(Task[] tasks, int millisecondsTimeout) => WaitAny(tasks, millisecondsTimeout, default);265 /// <summary>266 /// Waits for any of the provided <see cref="Task"/> objects to complete267 /// execution unless the wait is cancelled.268 /// </summary>269 [MethodImpl(MethodImplOptions.AggressiveInlining)]270 public static int WaitAny(Task[] tasks, CancellationToken cancellationToken) => WaitAny(tasks, Timeout.Infinite, cancellationToken);271 /// <summary>272 /// Waits for any of the provided <see cref="Task"/> objects to complete273 /// execution within a specified number of milliseconds or until a cancellation274 /// token is cancelled.275 /// </summary>276 [MethodImpl(MethodImplOptions.AggressiveInlining)]277 public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken) =>278 CoyoteRuntime.IsExecutionControlled ?279 CoyoteRuntime.Current.WaitAnyTaskCompletes(tasks) :280 Task.WaitAny(tasks, millisecondsTimeout, cancellationToken);281 /// <summary>282 /// Waits for the specified <see cref="Task"/> to complete execution.283 /// </summary>284 [MethodImpl(MethodImplOptions.AggressiveInlining)]285 public static void Wait(Task task) => Wait(task, Timeout.Infinite, default);286 /// <summary>287 /// Waits for the specified <see cref="Task"/> to complete execution within a specified time interval.288 /// </summary>289 [MethodImpl(MethodImplOptions.AggressiveInlining)]290 public static bool Wait(Task task, TimeSpan timeout)291 {292 long totalMilliseconds = (long)timeout.TotalMilliseconds;293 if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)294 {295 throw new ArgumentOutOfRangeException(nameof(timeout));296 }297 return Wait(task, (int)totalMilliseconds, default);298 }299 /// <summary>300 /// Waits for the specified <see cref="Task"/> to complete execution within a specified number of milliseconds.301 /// </summary>302 [MethodImpl(MethodImplOptions.AggressiveInlining)]303 public static bool Wait(Task task, int millisecondsTimeout) => Wait(task, millisecondsTimeout, default);304 /// <summary>305 /// Waits for the specified <see cref="Task"/> to complete execution. The wait terminates if a cancellation306 /// token is canceled before the task completes.307 /// </summary>308 [MethodImpl(MethodImplOptions.AggressiveInlining)]309 public static void Wait(Task task, CancellationToken cancellationToken) => Wait(task, Timeout.Infinite, cancellationToken);310 /// <summary>311 /// Waits for the specified <see cref="Task"/> to complete execution. The wait terminates if a timeout interval312 /// elapses or a cancellation token is canceled before the task completes.313 /// </summary>314 [MethodImpl(MethodImplOptions.AggressiveInlining)]315 public static bool Wait(Task task, int millisecondsTimeout, CancellationToken cancellationToken) =>316 CoyoteRuntime.IsExecutionControlled ?317 CoyoteRuntime.Current.WaitTaskCompletes(task) :318 task.Wait(millisecondsTimeout, cancellationToken);319 /// <summary>320 /// Returns a <see cref="CoyoteTasks.TaskAwaiter"/> for the specified <see cref="Task"/>.321 /// </summary>322 public static CoyoteTasks.TaskAwaiter GetAwaiter(Task task)323 {324 if (CoyoteRuntime.IsExecutionControlled)325 {326 var runtime = CoyoteRuntime.Current;327 runtime.AssertIsAwaitedTaskControlled(task);328 return new CoyoteTasks.TaskAwaiter(runtime, task);329 }330 return new CoyoteTasks.TaskAwaiter(null, task);331 }332 /// <summary>333 /// Configures an awaiter used to await this task.334 /// </summary>335 public static CoyoteTasks.ConfiguredTaskAwaitable ConfigureAwait(Task task, bool continueOnCapturedContext)336 {337 if (CoyoteRuntime.IsExecutionControlled)338 {339 var runtime = CoyoteRuntime.Current;340 runtime.AssertIsAwaitedTaskControlled(task);341 return new CoyoteTasks.ConfiguredTaskAwaitable(runtime, task, continueOnCapturedContext);342 }343 return new CoyoteTasks.ConfiguredTaskAwaitable(null, task, continueOnCapturedContext);344 }345 /// <summary>346 /// Creates an awaitable that asynchronously yields back to the current context when awaited.347 /// </summary>348 /// <remarks>349 /// You can use `await Task.Yield()` in an asynchronous method to force the method to complete350 /// asynchronously. During systematic testing, the underlying scheduling strategy can use this351 /// as a hint on how to better prioritize this work relative to other work that may be pending.352 /// </remarks>353 public static CoyoteTasks.YieldAwaitable Yield() =>354 new CoyoteTasks.YieldAwaitable(CoyoteRuntime.IsExecutionControlled ? CoyoteRuntime.Current : null);355 /// <summary>356 /// Injects a context switch point that can be systematically explored during testing.357 /// </summary>358 [MethodImpl(MethodImplOptions.AggressiveInlining)]359 public static void ExploreContextSwitch() => CoyoteRuntime.Current.ScheduleNextOperation(AsyncOperationType.Yield);360 }361 /// <summary>362 /// Provides methods for creating generic tasks that can be controlled during testing.363 /// </summary>364 /// <typeparam name="TResult">The type of the produced result.</typeparam>365 /// <remarks>This type is intended for compiler use rather than use directly in code.</remarks>366 [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]367 public static class ControlledTask<TResult>368 {369#pragma warning disable CA1000 // Do not declare static members on generic types370 /// <summary>371 /// Provides access to factory methods for creating controlled <see cref="Task"/>372 /// and <see cref="Task{TResult}"/> instances.373 /// </summary>374 public static TaskFactory<TResult> Factory { get; } = new TaskFactory<TResult>();375 /// <summary>376 /// Gets the result value of the specified <see cref="Task{TResult}"/>.377 /// </summary>378#pragma warning disable CA1707 // Remove the underscores from member name379#pragma warning disable SA1300 // Element should begin with an uppercase letter380#pragma warning disable IDE1006 // Naming Styles381 public static TResult get_Result(Task<TResult> task) => CoyoteRuntime.IsExecutionControlled ?382 CoyoteRuntime.Current.WaitTaskCompletes(task) : task.Result;383#pragma warning restore CA1707 // Remove the underscores from member name384#pragma warning restore SA1300 // Element should begin with an uppercase letter385#pragma warning restore IDE1006 // Naming Styles386 /// <summary>387 /// Returns a <see cref="CoyoteTasks.TaskAwaiter{TResult}"/> for the specified <see cref="Task{TResult}"/>.388 /// </summary>389 public static CoyoteTasks.TaskAwaiter<TResult> GetAwaiter(Task<TResult> task)390 {391 if (CoyoteRuntime.IsExecutionControlled)392 {393 var runtime = CoyoteRuntime.Current;394 runtime.AssertIsAwaitedTaskControlled(task);395 return new CoyoteTasks.TaskAwaiter<TResult>(runtime, task);396 }...

Full Screen

Full Screen

ControlledMachineTaskScheduler.cs

Source:ControlledMachineTaskScheduler.cs Github

copy

Full Screen

...187 }188 /// <summary>189 /// Sets the action to perform when the yield operation completes.190 /// </summary>191 internal override void OnYieldCompleted(Action continuation, YieldAwaiter awaiter) =>192 this.DispatchYield(continuation);193 /// <summary>194 /// Schedules the continuation action that is invoked when the yield operation completes.195 /// </summary>196 internal override void UnsafeOnYieldCompleted(Action continuation, YieldAwaiter awaiter) =>197 this.DispatchYield(continuation);198 /// <summary>199 /// Dispatches the work.200 /// </summary>201 private void DispatchYield(Action continuation)202 {203 try204 {205 AsyncActor caller = this.Runtime.GetExecutingActor<AsyncActor>();206 this.Runtime.Assert(caller != null,207 "Task with id '{0}' that is not controlled by the Coyote runtime invoked yield operation.",208 Task.CurrentId.HasValue ? Task.CurrentId.Value.ToString() : "<unknown>");209 if (caller is Actor actor)210 {...

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Runtime;6using Microsoft.Coyote.Tasks;7{8 {9 static async Task Main(string[] args)10 {11 var task = Task.Run(() => {12 var op = Operation.Current;13 op.Complete();14 });15 await task;16 }17 }18}19using System;20using System.Threading.Tasks;21using Microsoft.Coyote;22using Microsoft.Coyote.Actors;23using Microsoft.Coyote.Runtime;24using Microsoft.Coyote.Tasks;25{26 {27 static async Task Main(string[] args)28 {29 var task = Task.Run(() => {30 var op = Operation.Current;31 op.Complete();32 });33 await task;34 }35 }36}

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Runtime;2using System;3using System.Threading.Tasks;4{5 {6 static async Task Main(string[] args)7 {8 Console.WriteLine("Hello World!");9 var op = new Operation();10 op.Complete();11 await op;12 }13 }14}15using Microsoft.Coyote.Runtime;16using System;17using System.Threading.Tasks;18{19 {20 static async Task Main(string[] args)21 {22 Console.WriteLine("Hello World!");23 var op = new Operation();24 op.Complete();25 await op;26 }27 }28}29using Microsoft.Coyote.Runtime;30using System;31using System.Threading.Tasks;32{33 {34 static async Task Main(string[] args)35 {36 Console.WriteLine("Hello World!");37 var op = new Operation();38 op.Complete();39 await op;40 }41 }42}43using Microsoft.Coyote.Runtime;44using System;45using System.Threading.Tasks;46{47 {48 static async Task Main(string[] args)49 {50 Console.WriteLine("Hello World!");51 var op = new Operation();52 op.Complete();53 await op;54 }55 }56}57using Microsoft.Coyote.Runtime;58using System;59using System.Threading.Tasks;60{61 {62 static async Task Main(string[] args)63 {64 Console.WriteLine("Hello World!");65 var op = new Operation();66 op.Complete();67 await op;68 }69 }70}71using Microsoft.Coyote.Runtime;72using System;73using System.Threading.Tasks;74{75 {76 static async Task Main(string[] args)77 {78 Console.WriteLine("Hello World!");79 var op = new Operation();80 op.Complete();81 await op;82 }

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote;2using Microsoft.Coyote.Actors;3using Microsoft.Coyote.Specifications;4using System;5using System.Threading.Tasks;6{7 {8 public Actor1(ActorId id, ActorRuntime runtime) : base(id, runtime)9 {10 }11 protected override Task OnInitializeAsync(Event initialEvent)12 {13 this.SendEvent(this.Id, new E1());14 return Task.CompletedTask;15 }16 [OnEventDoAction(typeof(E1), nameof(F1))]17 {18 }19 private void F1()20 {21 this.SendEvent(this.Id, new E2());22 }23 [OnEventDoAction(typeof(E2), nameof(F2))]24 {25 }26 private void F2()27 {28 this.SendEvent(this.Id, new E3());29 }30 [OnEventDoAction(typeof(E3), nameof(F3))]31 {32 }33 private void F3()34 {35 this.SendEvent(this.Id, new E4());36 }37 [OnEventDoAction(typeof(E4), nameof(F4))]38 {39 }40 private void F4()41 {42 this.SendEvent(this.Id, new E5());43 }44 [OnEventDoAction(typeof(E5), nameof(F5))]45 {46 }47 private void F5()48 {49 this.SendEvent(this.Id, new E6());50 }51 [OnEventDoAction(typeof(E6), nameof(F6))]52 {53 }54 private void F6()55 {56 this.SendEvent(this.Id, new E7());57 }58 [OnEventDoAction(typeof(E7), nameof(F7))]59 {60 }61 private void F7()62 {63 this.SendEvent(this.Id, new E8());64 }65 [OnEventDoAction(typeof(E8), nameof(F8))]66 {67 }68 private void F8()69 {70 this.SendEvent(this.Id, new E9());71 }72 [OnEventDoAction(typeof(E9), nameof(F9))]

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Runtime;2using System;3using System.Threading.Tasks;4{5 {6 static async Task Main(string[] args)7 {8 var op = new Operation();9 op.Start();10 await op.Complete();11 Console.WriteLine("Hello World!");12 }13 }14}15using Microsoft.Coyote.Runtime;16using System;17using System.Threading.Tasks;18{19 {20 static void Main(string[] args)21 {22 var op = new Operation();23 op.Start();24 op.Complete().Wait();25 Console.WriteLine("Hello World!");26 }27 }28}29using Microsoft.Coyote.Runtime;30using System;31using System.Threading.Tasks;32{33 {34 static void Main(string[] args)35 {36 var op = new Operation();37 op.Start();38 op.Complete().GetAwaiter().GetResult();39 Console.WriteLine("Hello World!");40 }41 }42}43using Microsoft.Coyote.Runtime;44using System;45using System.Threading.Tasks;46{47 {48 static void Main(string[] args)49 {50 var op = new Operation();51 op.Start();52 op.Complete().ContinueWith(t => { }).Wait();53 Console.WriteLine("Hello World!");54 }55 }56}57using Microsoft.Coyote.Runtime;58using System;59using System.Threading.Tasks;60{61 {62 static void Main(string[] args)63 {64 var op = new Operation();65 op.Start();66 op.Complete().ContinueWith(t => { }).GetAwaiter().GetResult();67 Console.WriteLine("Hello World!");68 }69 }70}71using Microsoft.Coyote.Runtime;72using System;73using System.Threading.Tasks;74{75 {76 static void Main(string[] args)

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Runtime;2using System;3using System.Threading.Tasks;4{5 {6 static void Main(string[] args)7 {8 Console.WriteLine("Hello World!");9 Console.ReadKey();10 var op = new Operation();11 op.Complete();12 }13 }14}15using Microsoft.Coyote.Runtime;16using System;17using System.Threading.Tasks;18{19 {20 static void Main(string[] args)21 {22 Console.WriteLine("Hello World!");23 Console.ReadKey();24 var op = new Operation();25 op.Complete();26 }27 }28}29using Microsoft.Coyote.Runtime;30using System;31using System.Threading.Tasks;32{33 {34 static void Main(string[] args)35 {36 Console.WriteLine("Hello World!");37 Console.ReadKey();38 var op = new Operation();39 op.Complete();40 }41 }42}43using Microsoft.Coyote.Runtime;44using System;45using System.Threading.Tasks;46{47 {48 static void Main(string[] args)49 {50 Console.WriteLine("Hello World!");51 Console.ReadKey();52 var op = new Operation();53 op.Complete();54 }55 }56}57using Microsoft.Coyote.Runtime;58using System;59using System.Threading.Tasks;60{61 {62 static void Main(string[] args)63 {64 Console.WriteLine("Hello World!");65 Console.ReadKey();66 var op = new Operation();67 op.Complete();68 }69 }70}71using Microsoft.Coyote.Runtime;72using System;73using System.Threading.Tasks;74{75 {76 static void Main(string[] args)77 {78 Console.WriteLine("Hello World!");79 Console.ReadKey();80 var op = new Operation();81 op.Complete();82 }83 }84}

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using Microsoft.Coyote.Runtime;2using System;3{4 {5 static void Main(string[] args)6 {7 Console.WriteLine("Hello World!");8 var op = new Operation();9 op.Complete();10 }11 }12}13using Microsoft.Coyote.Runtime;14using System;15{16 {17 static void Main(string[] args)18 {19 Console.WriteLine("Hello World!");20 var op = new Operation();21 op.Complete();22 }23 }24}

Full Screen

Full Screen

Complete

Using AI Code Generation

copy

Full Screen

1using System;2using Microsoft.Coyote;3{4 {5 static void Main(string[] args)6 {7 Operation op = Operation.Create();8 op.Complete();9 op.Wait();10 }11 }12}13using System;14using Microsoft.Coyote;15{16 {17 static void Main(string[] args)18 {19 Operation op = Operation.Create();20 op.Complete();21 op.Wait();22 }23 }24}25using System;26using Microsoft.Coyote;27{28 {29 static void Main(string[] args)30 {31 Operation op = Operation.Create();32 op.Complete();33 op.Wait();34 }35 }36}37using System;38using Microsoft.Coyote;39{40 {41 static void Main(string[] args)42 {43 Operation op = Operation.Create();44 op.Complete();45 op.Wait();46 }47 }48}49using System;50using Microsoft.Coyote;51{52 {53 static void Main(string[] args)54 {55 Operation op = Operation.Create();56 op.Complete();57 op.Wait();58 }59 }60}61using System;62using Microsoft.Coyote;

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Coyote automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful