246 lines · 8.3 KB · C#
RawDownload
//******************************************************************************************************//  LogicalThread.cs - Gbtc////  Copyright © 2015, Grid Protection Alliance.  All Rights Reserved.////  Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See//  the NOTICE file distributed with this work for additional information regarding copyright ownership.//  The GPA licenses this file to you under the MIT License (MIT), the "License"; you may//  not use this file except in compliance with the License. You may obtain a copy of the License at:////      http://opensource.org/licenses/MIT////  Unless agreed to in writing, the subject software distributed under the License is distributed on an//  "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the//  License for the specific language governing permissions and limitations.////  Code Modification History://  ----------------------------------------------------------------------------------------------------//  09/24/2015 - Stephen C. Wills//       Generated original version of source code.////****************************************************************************************************** using System;using System.Collections.Concurrent;using System.Collections.Generic;using System.Threading; namespace GSF.Threading{    /// <summary>    /// Represents a thread of execution to which    /// actions can be dispatched from other threads.    /// </summary>    /// <remarks>    /// <para>    /// This class provides a simple alternative to synchronization primitives    /// such as wait handles and locks. Actions dispatched to a logical thread    /// will be processed synchronously as though it was executed as consecutive    /// method calls. All such actions can be dispatched from any thread in the    /// system so method calls coming from multiple threads can be easily    /// synchronized without locks, loops, wait handles, or timeouts.    /// </para>    ///     /// <para>    /// Note that the <see cref="LogicalThreadScheduler"/> implements its own    /// thread pool to execute tasks pushed to logical threads. Executing    /// long-running processes or using synchronization primitives with high    /// contention or long timeouts can hinder the logical thread scheduler's    /// ability to schedule the actions of other logical threads. Like other    /// thread pool implementations, you can mitigate this by increasing the    /// maximum thread count of the logical thread scheduler, however it is    /// recommended to avoid using synchronization primitives and instead    /// synchronize those operations by running them as separate actions on    /// the same logical thread.    /// </para>    /// </remarks>    public class LogicalThread    {        #region [ Members ]         // Events         /// <summary>        /// Handler for unhandled exceptions on the thread.        /// </summary>        public event EventHandler<EventArgs<Exception>> UnhandledException;         // Fields        private LogicalThreadScheduler m_scheduler;        private ConcurrentQueue<Action> m_queue;        private Dictionary<Guid, object> m_threadLocalStorage;        private int m_isActive;         #endregion         #region [ Constructors ]         /// <summary>        /// Creates a new instance of the <see cref="LogicalThread"/> class.        /// </summary>        public LogicalThread()            : this(DefaultScheduler)        {        }         /// <summary>        /// Creates a new instance of the <see cref="LogicalThread"/> class.        /// </summary>        /// <param name="scheduler">The <see cref="LogicalThreadScheduler"/> that created this thread.</param>        internal LogicalThread(LogicalThreadScheduler scheduler)        {            if ((object)scheduler == null)                throw new ArgumentNullException("scheduler");             m_scheduler = scheduler;            m_queue = new ConcurrentQueue<Action>();            m_threadLocalStorage = new Dictionary<Guid, object>();        }         #endregion         #region [ Properties ]         /// <summary>        /// Gets a flag that indicates whether the logical        /// thread has any unprocessed actions left in its queue.        /// </summary>        public bool HasAction        {            get            {                return !m_queue.IsEmpty;            }        }         #endregion         #region [ Methods ]         /// <summary>        /// Pushes an action to the logical thread.        /// </summary>        /// <param name="action">The action to be executed on this thread.</param>        public void Push(Action action)        {            ConcurrentQueue<Action> queue = m_queue;             if ((object)queue != null)            {                m_queue.Enqueue(action);                m_scheduler.SignalItemHandler(this);            }        }         /// <summary>        /// Clears all actions from the logical thread.        /// </summary>        public void Clear()        {            Action action;             while (!m_queue.IsEmpty)                m_queue.TryDequeue(out action);        }         /// <summary>        /// Pulls an action from the logical thread's internal queue to be executed on a physical thread.        /// </summary>        /// <returns>An action from the logical thread's internal queue.</returns>        internal Action Pull()        {            Action action;             return m_queue.TryDequeue(out action)                ? action                : null;        }         /// <summary>        /// Activates the thread if it is not already active.        /// </summary>        /// <returns>True if this call to TryActivate caused the thread to be active.</returns>        internal bool TryActivate()        {            return Interlocked.CompareExchange(ref m_isActive, 1, 0) == 0;        }         /// <summary>        /// Deactivates the thread.        /// </summary>        internal void Deactivate()        {            Interlocked.Exchange(ref m_isActive, 0);        }         /// <summary>        /// Returns the thread local object with the given ID.        /// </summary>        /// <param name="id">The ID of the thread local object.</param>        /// <returns>The value of the thread local object with the given ID.</returns>        internal object GetThreadLocal(Guid id)        {            object value;            m_threadLocalStorage.TryGetValue(id, out value);            return value;        }         /// <summary>        /// Sets the value of the thread local object with the given ID.        /// </summary>        /// <param name="id">The ID of the thread local object.</param>        /// <param name="value">The new value for the thread local object.</param>        internal void SetThreadLocal(Guid id, object value)        {            if (value != null)                m_threadLocalStorage[id] = value;            else                m_threadLocalStorage.Remove(id);        }         /// <summary>        /// Raises the <see cref="UnhandledException"/> event.        /// </summary>        /// <param name="ex">The unhandled exception.</param>        /// <returns>True if there are any handlers attached to this event; false otherwise.</returns>        internal bool OnUnhandledException(Exception ex)        {            EventHandler<EventArgs<Exception>> unhandledException = UnhandledException;             if ((object)unhandledException == null)                return false;             unhandledException(this, new EventArgs<Exception>(ex));             return true;        }         #endregion         #region [ Static ]         // Static Fields        private static readonly LogicalThreadScheduler DefaultScheduler = new LogicalThreadScheduler();        private static readonly ThreadLocal<LogicalThread> LocalThread = new ThreadLocal<LogicalThread>();         // Static Properties         /// <summary>        /// Gets the logical thread that is currently executing.        /// </summary>        public static LogicalThread CurrentThread        {            get            {                return LocalThread.Value;            }            internal set            {                LocalThread.Value = value;            }        }         #endregion    }}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t