Best Coyote code snippet using Microsoft.Coyote.Actors.ActorExecutionContext.GetNextOperationId
CoyoteRuntime.cs
Source:CoyoteRuntime.cs
...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>1288 internal int GetNondeterministicIntegerChoice(int maxValue, string callerName, string callerType) =>1289 this.DefaultActorExecutionContext.GetNondeterministicIntegerChoice(maxValue, callerName, callerType);1290 /// <summary>1291 /// Returns the next available unique operation id.1292 /// </summary>1293 /// <returns>Value representing the next available unique operation id.</returns>1294 internal ulong GetNextOperationId() =>1295 // Atomically increments and safely wraps the value into an unsigned long.1296 (ulong)Interlocked.Increment(ref this.OperationIdCounter) - 1;1297 /// <summary>1298 /// Gets the <see cref="AsyncOperation"/> that is executing on the current1299 /// synchronization context, or null if no such operation is executing.1300 /// </summary>1301 internal TAsyncOperation GetExecutingOperation<TAsyncOperation>()1302 where TAsyncOperation : AsyncOperation =>1303 this.Scheduler.GetExecutingOperation<TAsyncOperation>();1304 /// <summary>1305 /// Schedules the next controlled asynchronous operation. This method1306 /// is only used during testing.1307 /// </summary>1308 internal void ScheduleNextOperation(AsyncOperationType type = AsyncOperationType.Default, bool isYielding = false, int[] hashArray = null)...
ActorExecutionContext.cs
Source:ActorExecutionContext.cs
...116 this.ValueGenerator = valueGenerator;117 this.LogWriter = logWriter;118 }119 /// <inheritdoc/>120 public ActorId CreateActorId(Type type, string name = null) => new ActorId(type, this.GetNextOperationId(), name, this);121 /// <inheritdoc/>122 public virtual ActorId CreateActorIdFromName(Type type, string name) => new ActorId(type, 0, name, this, true);123 /// <inheritdoc/>124 public virtual ActorId CreateActor(Type type, Event initialEvent = null, EventGroup eventGroup = null) =>125 this.CreateActor(null, type, null, initialEvent, null, eventGroup);126 /// <inheritdoc/>127 public virtual ActorId CreateActor(Type type, string name, Event initialEvent = null, EventGroup eventGroup = null) =>128 this.CreateActor(null, type, name, initialEvent, null, eventGroup);129 /// <inheritdoc/>130 public virtual ActorId CreateActor(ActorId id, Type type, Event initialEvent = null, EventGroup eventGroup = null) =>131 this.CreateActor(id, type, null, initialEvent, null, eventGroup);132 /// <inheritdoc/>133 public virtual Task<ActorId> CreateActorAndExecuteAsync(Type type, Event initialEvent = null, EventGroup eventGroup = null) =>134 this.CreateActorAndExecuteAsync(null, type, null, initialEvent, null, eventGroup);135 /// <inheritdoc/>136 public virtual Task<ActorId> CreateActorAndExecuteAsync(Type type, string name, Event initialEvent = null, EventGroup eventGroup = null) =>137 this.CreateActorAndExecuteAsync(null, type, name, initialEvent, null, eventGroup);138 /// <inheritdoc/>139 public virtual Task<ActorId> CreateActorAndExecuteAsync(ActorId id, Type type, Event initialEvent = null, EventGroup eventGroup = null) =>140 this.CreateActorAndExecuteAsync(id, type, null, initialEvent, null, eventGroup);141 /// <summary>142 /// Creates a new <see cref="Actor"/> of the specified <see cref="Type"/>.143 /// </summary>144 internal virtual ActorId CreateActor(ActorId id, Type type, string name, Event initialEvent, Actor creator, EventGroup eventGroup)145 {146 Actor actor = this.CreateActor(id, type, name, creator, eventGroup);147 if (actor is StateMachine)148 {149 this.LogWriter.LogCreateStateMachine(actor.Id, creator?.Id.Name, creator?.Id.Type);150 }151 else152 {153 this.LogWriter.LogCreateActor(actor.Id, creator?.Id.Name, creator?.Id.Type);154 }155 this.RunActorEventHandler(actor, initialEvent, true);156 return actor.Id;157 }158 /// <summary>159 /// Creates a new <see cref="Actor"/> of the specified <see cref="Type"/>. The method160 /// returns only when the actor is initialized and the <see cref="Event"/> (if any)161 /// is handled.162 /// </summary>163 internal virtual async Task<ActorId> CreateActorAndExecuteAsync(ActorId id, Type type, string name, Event initialEvent,164 Actor creator, EventGroup eventGroup)165 {166 Actor actor = this.CreateActor(id, type, name, creator, eventGroup);167 if (actor is StateMachine)168 {169 this.LogWriter.LogCreateStateMachine(actor.Id, creator?.Id.Name, creator?.Id.Type);170 }171 else172 {173 this.LogWriter.LogCreateActor(actor.Id, creator?.Id.Name, creator?.Id.Type);174 }175 await this.RunActorEventHandlerAsync(actor, initialEvent, true);176 return actor.Id;177 }178 /// <summary>179 /// Creates a new <see cref="Actor"/> of the specified <see cref="Type"/>.180 /// </summary>181 internal virtual Actor CreateActor(ActorId id, Type type, string name, Actor creator, EventGroup eventGroup)182 {183 if (!type.IsSubclassOf(typeof(Actor)))184 {185 this.Assert(false, "Type '{0}' is not an actor.", type.FullName);186 }187 if (id is null)188 {189 id = this.CreateActorId(type, name);190 }191 else if (id.Runtime != null && id.Runtime != this)192 {193 this.Assert(false, "Unbound actor id '{0}' was created by another runtime.", id.Value);194 }195 else if (id.Type != type.FullName)196 {197 this.Assert(false, "Cannot bind actor id '{0}' of type '{1}' to an actor of type '{2}'.",198 id.Value, id.Type, type.FullName);199 }200 else201 {202 id.Bind(this);203 }204 // If no event group is provided then inherit the current group from the creator.205 if (eventGroup is null && creator != null)206 {207 eventGroup = creator.EventGroup;208 }209 Actor actor = ActorFactory.Create(type);210 IEventQueue eventQueue = new EventQueue(actor);211 actor.Configure(this, id, null, eventQueue, eventGroup);212 actor.SetupEventHandlers();213 if (!this.ActorMap.TryAdd(id, actor))214 {215 this.Assert(false, $"An actor with id '{id.Value}' was already created by another runtime instance.");216 }217 return actor;218 }219 /// <inheritdoc/>220 public virtual void SendEvent(ActorId targetId, Event initialEvent, EventGroup eventGroup = default, SendOptions options = null) =>221 this.SendEvent(targetId, initialEvent, null, eventGroup, options);222 /// <inheritdoc/>223 public virtual Task<bool> SendEventAndExecuteAsync(ActorId targetId, Event initialEvent,224 EventGroup eventGroup = null, SendOptions options = null) =>225 this.SendEventAndExecuteAsync(targetId, initialEvent, null, eventGroup, options);226 /// <summary>227 /// Sends an asynchronous <see cref="Event"/> to an actor.228 /// </summary>229 internal virtual void SendEvent(ActorId targetId, Event e, Actor sender, EventGroup eventGroup, SendOptions options)230 {231 EnqueueStatus enqueueStatus = this.EnqueueEvent(targetId, e, sender, eventGroup, out Actor target);232 if (enqueueStatus is EnqueueStatus.EventHandlerNotRunning)233 {234 this.RunActorEventHandler(target, null, false);235 }236 }237 /// <summary>238 /// Sends an asynchronous <see cref="Event"/> to an actor. Returns immediately if the target was239 /// already running. Otherwise blocks until the target handles the event and reaches quiescense.240 /// </summary>241 internal virtual async Task<bool> SendEventAndExecuteAsync(ActorId targetId, Event e, Actor sender,242 EventGroup eventGroup, SendOptions options)243 {244 EnqueueStatus enqueueStatus = this.EnqueueEvent(targetId, e, sender, eventGroup, out Actor target);245 if (enqueueStatus is EnqueueStatus.EventHandlerNotRunning)246 {247 await this.RunActorEventHandlerAsync(target, null, false);248 return true;249 }250 return enqueueStatus is EnqueueStatus.Dropped;251 }252 /// <summary>253 /// Enqueues an event to the actor with the specified id.254 /// </summary>255 private EnqueueStatus EnqueueEvent(ActorId targetId, Event e, Actor sender, EventGroup eventGroup, out Actor target)256 {257 if (e is null)258 {259 string message = sender != null ?260 string.Format("{0} is sending a null event.", sender.Id.ToString()) :261 "Cannot send a null event.";262 this.Assert(false, message);263 }264 if (targetId is null)265 {266 string message = (sender != null) ?267 string.Format("{0} is sending event {1} to a null actor.", sender.Id.ToString(), e.ToString())268 : string.Format("Cannot send event {0} to a null actor.", e.ToString());269 this.Assert(false, message);270 }271 target = this.GetActorWithId<Actor>(targetId);272 // If no group is provided we default to passing along the group from the sender.273 if (eventGroup is null && sender != null)274 {275 eventGroup = sender.EventGroup;276 }277 Guid opId = eventGroup is null ? Guid.Empty : eventGroup.Id;278 if (target is null || target.IsHalted)279 {280 this.LogWriter.LogSendEvent(targetId, sender?.Id.Name, sender?.Id.Type,281 (sender as StateMachine)?.CurrentStateName ?? default, e, opId, isTargetHalted: true);282 this.HandleDroppedEvent(e, targetId);283 return EnqueueStatus.Dropped;284 }285 this.LogWriter.LogSendEvent(targetId, sender?.Id.Name, sender?.Id.Type,286 (sender as StateMachine)?.CurrentStateName ?? default, e, opId, isTargetHalted: false);287 EnqueueStatus enqueueStatus = target.Enqueue(e, eventGroup, null);288 if (enqueueStatus == EnqueueStatus.Dropped)289 {290 this.HandleDroppedEvent(e, targetId);291 }292 return enqueueStatus;293 }294 /// <summary>295 /// Runs a new asynchronous actor event handler.296 /// This is a fire and forget invocation.297 /// </summary>298 private void RunActorEventHandler(Actor actor, Event initialEvent, bool isFresh)299 {300 Task.Run(async () =>301 {302 try303 {304 if (isFresh)305 {306 await actor.InitializeAsync(initialEvent);307 }308 await actor.RunEventHandlerAsync();309 }310 catch (Exception ex)311 {312 this.Scheduler.IsProgramExecuting = false;313 this.RaiseOnFailureEvent(ex);314 }315 finally316 {317 if (actor.IsHalted)318 {319 this.ActorMap.TryRemove(actor.Id, out Actor _);320 }321 }322 });323 }324 /// <summary>325 /// Runs a new asynchronous actor event handler.326 /// </summary>327 private async Task RunActorEventHandlerAsync(Actor actor, Event initialEvent, bool isFresh)328 {329 try330 {331 if (isFresh)332 {333 await actor.InitializeAsync(initialEvent);334 }335 await actor.RunEventHandlerAsync();336 }337 catch (Exception ex)338 {339 this.Scheduler.IsProgramExecuting = false;340 this.RaiseOnFailureEvent(ex);341 return;342 }343 }344 /// <summary>345 /// Creates a new timer that sends a <see cref="TimerElapsedEvent"/> to its owner actor.346 /// </summary>347 internal virtual IActorTimer CreateActorTimer(TimerInfo info, Actor owner) => new ActorTimer(info, owner);348 /// <inheritdoc/>349 public virtual EventGroup GetCurrentEventGroup(ActorId currentActorId)350 {351 Actor actor = this.GetActorWithId<Actor>(currentActorId);352 return actor?.CurrentEventGroup;353 }354 /// <summary>355 /// Gets the actor of type <typeparamref name="TActor"/> with the specified id,356 /// or null if no such actor exists.357 /// </summary>358 internal TActor GetActorWithId<TActor>(ActorId id)359 where TActor : Actor =>360 id != null && this.ActorMap.TryGetValue(id, out Actor value) &&361 value is TActor actor ? actor : null;362 /// <summary>363 /// Returns the next available unique operation id.364 /// </summary>365 /// <returns>Value representing the next available unique operation id.</returns>366 internal ulong GetNextOperationId() => this.Runtime.GetNextOperationId();367 /// <inheritdoc/>368 public bool RandomBoolean() => this.GetNondeterministicBooleanChoice(2, null, null);369 /// <inheritdoc/>370 public bool RandomBoolean(int maxValue) => this.GetNondeterministicBooleanChoice(maxValue, null, null);371 /// <summary>372 /// Returns a controlled nondeterministic boolean choice.373 /// </summary>374 internal virtual bool GetNondeterministicBooleanChoice(int maxValue, string callerName, string callerType)375 {376 bool result = false;377 if (this.ValueGenerator.Next(maxValue) is 0)378 {379 result = true;380 }...
GetNextOperationId
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using Microsoft.Coyote.Actors;4using Microsoft.Coyote.Runtime;5{6 {7 static async Task Main(string[] args)8 {9 var config = Configuration.Create();10 config.MaxSchedulingSteps = 1000000;11 config.MaxFairSchedulingSteps = 1000000;
GetNextOperationId
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using Microsoft.Coyote.Actors;4using Microsoft.Coyote.Specifications;5using Microsoft.Coyote.SystematicTesting;6using Microsoft.Coyote.Tasks;7{8 {9 static void Main(string[] args)10 {11 using (var runtime = RuntimeFactory.Create())12 {13 var configuration = Configuration.Create();14 configuration.SchedulingIterations = 1000;15 configuration.SchedulingStrategy = SchedulingStrategy.Random;16 configuration.TestingIterations = 1000;17 configuration.Verbose = 2;18 configuration.ReportActivityCoverage = true;19 configuration.ReportFairScheduling = true;20 configuration.ReportOperationCoverage = true;21 configuration.ReportStateGraph = true;22 configuration.ReportStateGraphEdgeCoverage = true;23 configuration.ReportStateGraphEdgeCoverageThreshold = 0.5;24 configuration.ReportStateGraphMaxUnvisitedStates = 100;25 configuration.ReportStateGraphMaxUnvisitedTransitionsPerState = 100;26 configuration.ReportStateGraphStateCoverage = true;27 configuration.ReportStateGraphStateCoverageThreshold = 0.5;28 configuration.ReportStateGraphTransitionCoverage = true;29 configuration.ReportStateGraphTransitionCoverageThreshold = 0.5;30 configuration.ReportStateGraphUnvisitedStateLimit = 100;31 configuration.ReportStateGraphUnvisitedTransitionLimit = 100;32 configuration.ReportUnhandledExceptions = true;33 configuration.ReportUnhandledExceptionsAsFailures = true;34 configuration.ReportUnprovenLivenessProperties = true;35 configuration.ReportUnprovenSafetyProperties = true;36 configuration.ReportUnprovenSafetyPropertiesAsFailures = true;37 configuration.ReportUnprovenLivenessPropertiesAsFailures = true;38 configuration.ReportUnprovenSafetyPropertiesAsFailures = true;39 configuration.ReportUnprovenLivenessPropertiesAsFailures = true;40 configuration.ReportActivityCoverage = true;41 configuration.ReportFairScheduling = true;42 configuration.ReportOperationCoverage = true;43 configuration.ReportStateGraph = true;44 configuration.ReportStateGraphEdgeCoverage = true;45 configuration.ReportStateGraphEdgeCoverageThreshold = 0.5;46 configuration.ReportStateGraphMaxUnvisitedStates = 100;47 configuration.ReportStateGraphMaxUnvisitedTransitionsPerState = 100;48 configuration.ReportStateGraphStateCoverage = true;
GetNextOperationId
Using AI Code Generation
1using System;2using Microsoft.Coyote.Actors;3using Microsoft.Coyote.Actors.Timers;4{5 {6 public static void Main(string[] args)7 {8 var configuration = Configuration.Create();9 var runtime = RuntimeFactory.Create(configuration);10 runtime.CreateActor(typeof(Actor1));11 runtime.Wait();12 }13 }14 {15 private TimerInfo timer;16 protected override void OnInitialize(Event initialEvent)17 {18 this.timer = this.RegisterTimer(this.Id, new E(), 1000, true);19 }20 protected override void OnEvent(Event e)21 {22 this.SendEvent(this.Id, new E());23 }24 protected override void OnTimerElapsed(TimerInfo info)25 {26 if (info == this.timer)27 {28 Console.WriteLine("Timer elapsed");29 var nextOpId = this.GetNextOperationId();30 this.SendEvent(this.Id, new E(), nextOpId);31 }32 }33 }34 {35 }36}37Severity Code Description Project File Line Suppression State Error CS0535 'Program': cannot override inherited member 'Actor.OnEvent(Event)' because it is not marked virtual, abstract, or override CoyoteTest C:\Users\user\source\repos\CoyoteTest\Program.cs 14 Active38Severity Code Description Project File Line Suppression State Error CS0534 'Program' does not implement inherited abstract member 'Actor.OnEvent(Event)' CoyoteTest C:\Users\user\source\repos\CoyoteTest\Program.cs 14 Active
GetNextOperationId
Using AI Code Generation
1using Microsoft.Coyote.Actors;2using Microsoft.Coyote.Actors.Timers;3using System;4using System.Collections.Generic;5using System.Linq;6using System.Text;7using System.Threading.Tasks;8{9 {10 static void Main(string[] args)11 {12 Console.WriteLine(id);13 Console.ReadLine();14 }15 }16}
GetNextOperationId
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Specifications;6using Microsoft.Coyote.Tasks;7{8 [OnEventGotoState(typeof(Start), typeof(State1))]9 [OnEventGotoState(typeof(Event1), typeof(State2))]10 [OnEventGotoState(typeof(Event2), typeof(State1))]11 {12 [OnEntry(nameof(EntryAction1))]13 [OnEventDoAction(typeof(Event1), nameof(Action1))]14 {15 }16 [OnEntry(nameof(EntryAction2))]17 [OnEventDoAction(typeof(Event2), nameof(Action2))]18 {19 }20 void EntryAction1()21 {22 this.SendEvent(this.Id, new Event1());23 }24 void EntryAction2()25 {26 this.SendEvent(this.Id, new Event2());27 }28 void Action1()29 {30 }31 void Action2()32 {33 }34 }35 {36 }37 {38 }39 {40 static void Main(string[] args)41 {42 Runtime runtime = RuntimeFactory.Create();43 runtime.RegisterMonitor(typeof(Actor1));44 runtime.CreateActor(typeof(Actor1));45 runtime.Wait();46 }47 }48}
GetNextOperationId
Using AI Code Generation
1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;6using Microsoft.Coyote.Actors;7using Microsoft.Coyote.Actors.Timers;8{9 {10 static void Main(string[] args)11 {12 ActorId actorId = ActorId.CreateRandom();13 ActorRuntime runtime = new ActorRuntime();14 int operationId = runtime.GetNextOperationId(actorId);
GetNextOperationId
Using AI Code Generation
1using System;2using System.Threading.Tasks;3using Microsoft.Coyote;4using Microsoft.Coyote.Actors;5using Microsoft.Coyote.Runtime;6using Microsoft.Coyote.Tasks;7using Microsoft.Coyote.TestingServices;8using Microsoft.Coyote.TestingServices.Runtime;9using Microsoft.Coyote.TestingServices.SchedulingStrategies;10using Microsoft.Coyote.TestingServices.Tracing.Schedule;11using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default;12using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies;13{14 {15 protected override async Task OnInitializeAsync(Event initialEvent)16 {17 var context = this.Runtime.GetActorExecutionContext(this.Id);18 var nextOperationId = context.GetNextOperationId();19 Console.WriteLine("Next operation id of the actor: {0}", nextOperationId);20 }21 }22 {23 public static async Task Main(string[] args)24 {25 var runtime = RuntimeFactory.Create();26 var actor = runtime.CreateActor(typeof(MyActor));27 await runtime.StartAsync();28 await runtime.WaitAsync();29 }30 }31}32using System;33using System.Threading.Tasks;34using Microsoft.Coyote;35using Microsoft.Coyote.Actors;36using Microsoft.Coyote.Runtime;37using Microsoft.Coyote.Tasks;38using Microsoft.Coyote.TestingServices;39using Microsoft.Coyote.TestingServices.Runtime;40using Microsoft.Coyote.TestingServices.SchedulingStrategies;41using Microsoft.Coyote.TestingServices.Tracing.Schedule;42using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default;43using Microsoft.Coyote.TestingServices.Tracing.Schedule.Default.Strategies;44{
GetNextOperationId
Using AI Code Generation
1using Microsoft.Coyote;2using Microsoft.Coyote.Actors;3{4 {5 protected override async Task OnInitializeAsync(Event e)6 {7 var id = this.Runtime.GetNextOperationId();8 }9 }10}11using Microsoft.Coyote;12using Microsoft.Coyote.Actors;13{14 {15 protected override async Task OnInitializeAsync(Event e)16 {17 var id = this.Runtime.GetNextOperationId();18 }19 }20}21using Microsoft.Coyote;22using Microsoft.Coyote.Actors;23{24 {25 protected override async Task OnInitializeAsync(Event e)26 {27 var id = this.Runtime.GetNextOperationId();28 }29 }30}31using Microsoft.Coyote;32using Microsoft.Coyote.Actors;33{34 {35 protected override async Task OnInitializeAsync(Event e)36 {37 var id = this.Runtime.GetNextOperationId();38 }39 }40}41using Microsoft.Coyote;42using Microsoft.Coyote.Actors;43{44 {45 protected override async Task OnInitializeAsync(Event e)46 {47 var id = this.Runtime.GetNextOperationId();48 }49 }50}
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.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!