Esempio n. 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TaskEntry"/> class.
 /// </summary>
 public TaskEntry(int id, bool enabled, AsyncOperationType opType, AsyncOperationTarget target, int targetId, int sendStepIndex)
 {
     this.Id            = id;
     this.Enabled       = enabled;
     this.Sleep         = false;
     this.Backtrack     = false;
     this.OpType        = opType;
     this.OpTarget      = target;
     this.TargetId      = targetId;
     this.SendStepIndex = sendStepIndex;
 }
        /// <summary>
        /// Schedules the next asynchronous operation.
        /// </summary>
        internal void ScheduleNextOperation(AsyncOperationType type, AsyncOperationTarget target, ulong targetId)
        {
            int?taskId = Task.CurrentId;

            // If the caller is the root task, then return.
            if (taskId != null && taskId == this.Runtime.RootTaskId)
            {
                return;
            }

            if (!this.IsSchedulerRunning)
            {
                this.Stop();
                throw new ExecutionCanceledException();
            }

            // Checks if concurrency not controlled by the runtime was used.
            this.Runtime.AssertNoExternalConcurrencyUsed();

            // Checks if the scheduling steps bound has been reached.
            this.CheckIfSchedulingStepsBoundIsReached();

            AsyncOperation current = this.ScheduledOperation;

            current.SetNextOperation(type, target, targetId);

            // Get and order the operations by their id.
            var ops = this.OperationMap.Values.OrderBy(op => op.SourceId).Select(op => op as IAsyncOperation).ToList();

            if (!this.Strategy.GetNext(out IAsyncOperation next, ops, current))
            {
                // Checks if the program has livelocked.
                this.CheckIfProgramHasLivelocked(ops.Select(op => op as AsyncOperation));

                Debug.WriteLine("<ScheduleDebug> Schedule explored.");
                this.HasFullyExploredSchedule = true;
                this.Stop();
                throw new ExecutionCanceledException();
            }

            this.ScheduledOperation = next as AsyncOperation;
            this.Runtime.ScheduleTrace.AddSchedulingChoice(next.SourceId);

            Debug.WriteLine($"<ScheduleDebug> Schedule '{next.SourceName}' with task id '{this.ScheduledOperation.Task.Id}'.");

            if (current != next)
            {
                current.IsActive = false;
                lock (next)
                {
                    this.ScheduledOperation.IsActive = true;
                    System.Threading.Monitor.PulseAll(next);
                }

                lock (current)
                {
                    if (!current.IsInboxHandlerRunning)
                    {
                        return;
                    }

                    while (!current.IsActive)
                    {
                        Debug.WriteLine($"<ScheduleDebug> Sleep '{current.SourceName}' with task id '{current.Task.Id}'.");
                        System.Threading.Monitor.Wait(current);
                        Debug.WriteLine($"<ScheduleDebug> Wake up '{current.SourceName}' with task id '{current.Task.Id}'.");
                    }

                    if (!current.IsEnabled)
                    {
                        throw new ExecutionCanceledException();
                    }
                }
            }
        }
Esempio n. 3
0
 /// <summary>
 /// Sets the next operation to schedule.
 /// </summary>
 internal void SetNextOperation(AsyncOperationType operationType, AsyncOperationTarget target, ulong targetId)
 {
     this.Type     = operationType;
     this.Target   = target;
     this.TargetId = targetId;
 }