/// <summary> /// Create a task that waits until this code can be executed. /// It may be cancelled if this code is supposed to be cancelled before it is started /// </summary> /// <returns>Lock to maintain while the code is being executed internally</returns> /// <exception cref="OperationCanceledException">Code has been cancelled</exception> private Task <IDisposable> WaitForExecution() { // Get a cancellation token lock (_cancellationTokenSources) { CancellationToken = _cancellationTokenSources[(int)Channel].Token; } // Codes from interceptors do not have any order control to avoid deadlocks Code codeBeingIntercepted = Interception.GetCodeBeingIntercepted(SourceConnection); if (codeBeingIntercepted != null) { if (codeBeingIntercepted.Flags.HasFlag(CodeFlags.IsFromMacro)) { Flags |= CodeFlags.IsFromMacro; File = codeBeingIntercepted.File; Macro = codeBeingIntercepted.Macro; } return(Task.FromResult <IDisposable>(null)); } // Wait for pending high priority codes if (Flags.HasFlag(CodeFlags.IsPrioritized)) { _codeType = InternalCodeType.Prioritized; _logger.Debug("Waiting for execution of {0} (prioritized)", this); return(_codeStartLocks[(int)Channel, (int)InternalCodeType.Prioritized].LockAsync(CancellationToken)); } // Wait for pending codes from the current macro if (Flags.HasFlag(CodeFlags.IsFromMacro)) { _codeType = InternalCodeType.Macro; _logger.Debug("Waiting for execution of {0} (macro code)", this); return((Macro == null) ? _codeStartLocks[(int)Channel, (int)InternalCodeType.Macro].LockAsync(CancellationToken) : Macro.WaitForCodeStart()); } // Wait for pending codes for message acknowledgements // FIXME M0/M1 are not meant to be used while a message box is open if (!Flags.HasFlag(CodeFlags.IsFromFirmware) && Interface.IsWaitingForAcknowledgement(Channel) && (Type != CodeType.MCode || (MajorNumber != 0 && MajorNumber != 1))) { _codeType = InternalCodeType.Acknowledgement; _logger.Debug("Waiting for execution of {0} (acknowledgement)", this); return(_codeStartLocks[(int)Channel, (int)InternalCodeType.Acknowledgement].LockAsync(CancellationToken)); } // Wait for pending regular codes _codeType = InternalCodeType.Regular; _logger.Debug("Waiting for execution of {0}", this); return(_codeStartLocks[(int)Channel, (int)InternalCodeType.Regular].LockAsync(CancellationToken)); }