⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cnetmonitor.cs

📁 Perst开源实时数据库
💻 CS
字号:
using System;
using System.Threading;

namespace Perst.Impl  
{
    /// <summary>
    /// Enhanced alternative to the <see cref="T:System.Threading.Monitor"/> class.  Provides a mechanism that synchronizes access to objects.
    /// </summary>
    /// <seealso cref="T:System.Threading.Monitor"/>
    public sealed class CNetMonitor
    {
        /// <summary>
        /// The owner of the monitor, or null if it's not owned
        /// by any thread.
        /// </summary>
        Thread currentOwner=null;

        /// <summary>
        /// Number of levels of locking (0 for an unowned
        /// monitor, 1 after a single call to Enter, etc).
        /// </summary>
        int lockCount=0;

        /// <summary>
        /// Object to be used as a monitor for state changing.
        /// </summary>
        object stateLock = new object();

        /// <summary>
        /// AutoResetEvent used to implement Wait/Pulse/PulseAll.
        /// Initially not signalled, so that a call to Wait will
        /// block until the first pulse.
        /// </summary>
        AutoResetEvent waitPulseEvent = new AutoResetEvent(false);

        /// <summary>
        /// Number of threads waiting on this monitor.
        /// </summary>
        int waitCounter=0;

        /// <summary>
        /// Event used for Enter/Exit. Initially signalled
        /// to allow the first thread to come in.
        /// </summary>
        AutoResetEvent enterExitEvent = new AutoResetEvent(true);

        /// <summary>
        /// Creates a new monitor, not owned by any thread.
        /// </summary>
        public CNetMonitor()
        {
        }

        /// <summary>
        /// Enters the monitor (locks it), blocking until the
        /// lock is held. If the monitor is already held by the current thread,
        /// its lock count is incremented.
        /// </summary>
        public void Enter()
        {
            Thread currentThread = Thread.CurrentThread;
            while (true)
            {
                lock (stateLock)
                {
                    if(currentOwner==currentThread)
                    {
                        lockCount++;
                        return;
                    }
                }
                
                enterExitEvent.WaitOne();
                lock (stateLock)
                {
                    if (currentOwner==null)
                    {
                        currentOwner=currentThread;
                        lockCount=1;
                        enterExitEvent.Reset();
                        return;
                    }
                }
            }
        }

        /// <summary>
        /// Releases a level of locking, unlocking the monitor itself
        /// if the lock count becomes 0.
        /// </summary>
        /// <exception cref="SynchronizationLockException">If the current 
        /// thread does not own the monitor.</exception>
        public void Exit()
        {
            lock (stateLock)
            {
                if (currentOwner != Thread.CurrentThread)
                {
                    throw new 
                        SynchronizationLockException
                        ("Cannot Exit a monitor owned by a different thread.");
                }
                lockCount--;
                if (lockCount==0)
                {
                    currentOwner=null;
                    enterExitEvent.Set();
                }
            }
        }

        /// <summary>
        /// Pulses the monitor once - a single waiting thread will be released
        /// and continue its execution after the current thread has exited the
        /// monitor. Unlike Pulse on the normal framework, no guarantee is
        /// made about which thread is woken.
        /// </summary>
        /// <exception cref="SynchronizationLockException">If the 
        /// current thread does not own the monitor.</exception>
        public void Pulse()
        {
            lock (stateLock)
            {
                if (currentOwner != Thread.CurrentThread)
                {
                    throw new 
                        SynchronizationLockException
                        ("Cannot Exit a monitor owned by a different thread.");
                }
                // Don't bother setting the event if no-one's waiting - we'd only end
                // up having to reset the event manually.
                if (waitCounter==0)
                {
                    return;
                }
                waitPulseEvent.Set();
                waitCounter--;
            }
        }

        /// <summary>
        /// Pulses the monitor such that all waiting threads are woken up.
        /// All threads will then try to regain the lock on this monitor.
        /// No order for regaining the lock is specified.
        /// </summary>
        /// <exception cref="SynchronizationLockException">If the current 
        /// thread does not own the monitor.</exception>
        public void PulseAll()
        {
            lock (stateLock)
            {
                if (currentOwner != Thread.CurrentThread)
                {
                    throw new 
                        SynchronizationLockException
                        ("Cannot Exit a monitor owned by a different thread.");
                }
                for (int i=0; i < waitCounter; i++)
                {
                    waitPulseEvent.Set();
                }
                waitCounter=0;
            }
        }

        /// <summary>
        /// Relinquishes the lock on this monitor (whatever the lock count is)
        /// and waits for the monitor to be pulsed. After the monitor has been 
        /// pulsed, the thread blocks again until it has regained the lock (at 
        /// which point it will have the same lock count as it had before), and 
        /// then the method returns.
        /// </summary>
        public void Wait()
        {
            int oldLockCount;
            lock (stateLock)
            {
                if (currentOwner != Thread.CurrentThread)
                {
                    throw new 
                        SynchronizationLockException
                        ("Cannot Exit a monitor owned by a different thread.");
                }
                oldLockCount = lockCount;
                // Make Exit() set the enterExitEvent
                lockCount=1;
                Exit();
                waitCounter++;
            }
            waitPulseEvent.WaitOne();
            Enter();
            // By now we own the lock again
            lock (stateLock)
            {
                lockCount=oldLockCount;
            }
        }
    }

    /// <summary>
    /// Exception thrown by <see cref="Perst.Impl.CNetMonitor"/> when threading rules
    /// are violated (usually due to an operation being
    /// invoked on a monitor not owned by the current thread).
    /// </summary>
    public class SynchronizationLockException : SystemException
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="SynchronizationLockException"/> class with a specified error message.
        /// </summary>
        /// <param name="message">The error message that explains the reason for the exception.</param>
        public SynchronizationLockException(string message) : 
            base(message)
        {
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -