public bool PrioritizeAction(Action action)
        {
            ICancellationToken priorityToken = new GSF.Threading.CancellationToken();
            ICancellationToken normalToken   = null;
            bool cancelled = false;

            priorityToken.Cancel();

            while (Interlocked.CompareExchange(ref m_cancellationToken, priorityToken, normalToken) != normalToken)
            {
                normalToken = Interlocked.CompareExchange(ref m_cancellationToken, null, null);
                cancelled   = normalToken?.Cancel() ?? true;

                if (!cancelled)
                {
                    return(false);
                }
            }

            TaskThread.Push(HighPriority, () =>
            {
                try     { action(); }
                finally { Interlocked.Exchange(ref m_cancellationToken, null); }
            });

            return(true);
        }
Example #2
0
        /// <summary>
        /// Creates a new instance of the <see cref="LogicalThreadOperation"/> class.
        /// </summary>
        /// <param name="thread">The thread on which to execute the operation's action.</param>
        /// <param name="action">The action to be executed.</param>
        /// <param name="priority">The priority with which the action should be executed on the logical thread.</param>
        /// <param name="autoRunIfPending">
        /// Set to <c>true</c> to execute <see cref="RunIfPending"/> automatically; otherwise,
        /// set to <c>false</c> for user controlled call timing.
        /// </param>
        /// <exception cref="ArgumentException"><paramref name="priority"/> is outside the range between 1 and <see cref="LogicalThread.PriorityLevels"/>.</exception>
        public LogicalThreadOperation(LogicalThread thread, Action action, int priority, bool autoRunIfPending = true)
        {
            m_thread           = thread;
            m_action           = action;
            Priority           = priority;
            m_autoRunIfPending = autoRunIfPending;

            // Initialize this class with a cancelled token so that
            // calls to EnsurePriority before the first call to
            // ExecuteActionAsync do not inadvertently queue actions
            m_cancellationToken = new CancellationToken();
            m_cancellationToken.Cancel();
        }
Example #3
0
        /// <summary>
        /// Queues the given thread for execution.
        /// </summary>
        /// <param name="thread">The thread to be queued for execution.</param>
        private void Enqueue(LogicalThread thread)
        {
            ICancellationToken executionToken;
            int activePriority;
            int nextPriority;

            do
            {
                // Create the execution token to be used in the closure
                ICancellationToken nextExecutionToken = new CancellationToken();

                // Always update the thread's active priority before
                // the execution token to mitigate race conditions
                nextPriority              = thread.NextPriority;
                thread.ActivePriority     = nextPriority;
                thread.NextExecutionToken = nextExecutionToken;

                // Now that the action can be cancelled by another thread using the
                // new cancellation token, it should be safe to put it in the queue
                m_logicalThreadQueues[PriorityLevels - nextPriority].Enqueue(() =>
                {
                    if (nextExecutionToken.Cancel())
                    {
                        return(thread);
                    }

                    return(null);
                });

                // Because enqueuing the thread is a multi-step process, we need to
                // double-check in case the thread's priority changed in the meantime
                activePriority = thread.ActivePriority;
                nextPriority   = thread.NextPriority;

                // We can use the cancellation token we just created because we only
                // really need to double-check the work that was done on this thread;
                // in other words, if another thread changed the priority in the
                // meantime, it can double-check its own work
                executionToken = nextExecutionToken;
            }while (activePriority != nextPriority && executionToken.Cancel());
        }
Example #4
0
        private void ExecuteActionAsync(int priority)
        {
            CancellationToken cancellationToken = new CancellationToken();

            // Order of operations here is vital to avoid getting
            // cancelled when the user hasn't changed the priority level
            Interlocked.Exchange(ref m_queuedPriority, priority);
            Interlocked.Exchange(ref m_cancellationToken, cancellationToken);

            m_thread.Push(priority, () =>
            {
                // If the cancellation token was previously cancelled,
                // it means this action has been requeued so don't do anything.
                // By cancelling it now, we let requeue operations know that the
                // action is currently executing and will soon be requeued anyway
                if (m_cancellationToken.Cancel())
                {
                    ExecuteAction(m_action);
                }
            });
        }
        public bool QueueAction(Action action)
        {
            ICancellationToken cancellationToken = new GSF.Threading.CancellationToken();

            if (Interlocked.CompareExchange(ref m_cancellationToken, cancellationToken, null) != null)
            {
                return(false);
            }

            TaskThread.Push(NormalPriority, () =>
            {
                if (!cancellationToken.Cancel())
                {
                    return;
                }

                try     { action(); }
                finally { Interlocked.CompareExchange(ref m_cancellationToken, null, cancellationToken); }
            });

            return(true);
        }
            public void CancelEnumeration()
            {
                CancellationToken cancellationToken = Interlocked.CompareExchange(ref m_cancellationToken, null, null);

                cancellationToken?.Cancel();
            }