Ejemplo n.º 1
0
        /// <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));
        }