ThreadNeutralSemaphore.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / ThreadNeutralSemaphore.cs / 1 / ThreadNeutralSemaphore.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.Threading;
 
    class ThreadNeutralSemaphore
    {
#if DEBUG_EXPENSIVE
        StackTrace exitStack; 
#endif
        int count; 
        int maxCount; 
        Queue waiters;
        bool aborted; 
        object ThisLock = new object();

        public ThreadNeutralSemaphore(int maxCount)
        { 
            if (maxCount < 1)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxCount", maxCount, 
                    SR.GetString(SR.ValueMustBePositive))); 

            this.maxCount = maxCount; 
        }

        Queue Waiters
        { 
            get
            { 
                if (waiters == null) 
                {
                    waiters = new Queue(); 
                }

                return waiters;
            } 
        }
 
        public bool TryEnter() 
        {
            lock (ThisLock) 
            {
                if (this.count < this.maxCount)
                {
                    this.count++; 
                    return true;
                } 
 
                return false;
            } 
        }

        public bool Enter(WaitCallback callback, object state)
        { 
            if (callback == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("callback"); 
 
            lock (ThisLock)
            { 
                if (this.count < this.maxCount)
                {
                    this.count++;
                    return true; 
                }
 
                Waiters.Enqueue(new AsyncWaiter(callback, state)); 
                return false;
            } 
        }

        public void Enter()
        { 
            SyncWaiter waiter = EnterCore();
 
            if (waiter != null) 
                waiter.Wait();
        } 

        public bool TryEnter(TimeSpan timeout)
        {
            SyncWaiter waiter = EnterCore(); 

            if (waiter != null) 
            { 
                return waiter.Wait(timeout);
            } 
            else
            {
                return true;
            } 
        }
 
        public void Enter(TimeSpan timeout) 
        {
            if (!TryEnter(timeout)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateEnterTimedOutException(timeout));
            }
        } 

        internal static TimeoutException CreateEnterTimedOutException(TimeSpan timeout) 
        { 
            return new TimeoutException(SR.GetString(SR.ThreadAcquisitionTimedOut, timeout));
        } 

        static CommunicationObjectAbortedException CreateObjectAbortedException()
        {
            return new CommunicationObjectAbortedException(SR.GetString(SR.ThreadNeutralSemaphoreAborted)); 
        }
 
        // remove a waiter from our queue. Returns true if successful. Used to implement timeouts. 
        bool RemoveWaiter(Waiter waiter)
        { 
            bool removed = false;

            lock (ThisLock)
            { 
                for (int i = Waiters.Count; i > 0; i--)
                { 
                    Waiter temp = Waiters.Dequeue(); 
                    if (object.ReferenceEquals(temp, waiter))
                    { 
                        removed = true;
                    }
                    else
                    { 
                        Waiters.Enqueue(temp);
                    } 
                } 
            }
 
            return removed;
        }

        SyncWaiter EnterCore() 
        {
            SyncWaiter waiter; 
 
            lock (ThisLock)
            { 
                if (this.aborted)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThreadNeutralSemaphore.CreateObjectAbortedException());
                } 

                if (this.count < this.maxCount) 
                { 
                    this.count++;
                    return null; 
                }

                waiter = new SyncWaiter(this);
                Waiters.Enqueue(waiter); 
            }
 
            return waiter; 
        }
 
        public void Exit()
        {
            Waiter waiter;
 
            lock (ThisLock)
            { 
                if (this.count == 0) 
                {
                    string message = SR.GetString(SR.InvalidLockOperation); 

#if DEBUG_EXPENSIVE
                    if (exitStack != null)
                    { 
                        string originalStack = exitStack.ToString().Replace("\r\n", "\r\n    ");
                        message = SR.GetString(SR.InvalidLockOperationStack, originalStack); 
                    } 
#endif
 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SynchronizationLockException(message));
                }

                if (waiters == null || waiters.Count == 0) 
                {
                    this.count--; 
 
#if DEBUG_EXPENSIVE
                if (this.count == 0) 
                {
                    exitStack = new StackTrace();
                }
#endif 
                    return;
                } 
 
                waiter = waiters.Dequeue();
            } 

            waiter.Signal();
        }
 
        ///
        /// Abort the ThreadNeutralSemaphore object. 
        /// NOTE: This method is only supported for sync waiters. 
        ///
        public void Abort() 
        {
            lock (ThisLock)
            {
                if (aborted) 
                {
                    return; 
                } 

                aborted = true; 
                if (waiters != null)
                {
                    while (waiters.Count > 0)
                    { 
                        Waiter waiter = waiters.Dequeue();
                        waiter.Abort(); 
                    } 
                }
            } 
        }

        abstract class Waiter
        { 
            public abstract void Signal();
            public abstract void Abort(); 
        } 

        class AsyncWaiter : Waiter 
        {
            WaitCallback callback;
            object state;
 
            public AsyncWaiter(WaitCallback callback, object state)
            { 
                this.callback = callback; 
                this.state = state;
            } 

            public override void Signal()
            {
                IOThreadScheduler.ScheduleCallback(callback, state); 
            }
 
            public override void Abort() 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.ThreadNeutralSemaphoreAsyncAbort))); 
            }
        }

        class SyncWaiter : Waiter 
        {
            ThreadNeutralSemaphore parent; 
            AutoResetEvent waitHandle; 
            bool aborted;
 
            public SyncWaiter(ThreadNeutralSemaphore parent)
            {
                this.waitHandle = new AutoResetEvent(false);
                this.parent = parent; 
            }
 
            public void Wait() 
            {
                waitHandle.WaitOne(); 
                waitHandle.Close();

                if (this.aborted)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThreadNeutralSemaphore.CreateObjectAbortedException());
                } 
            } 

            public bool Wait(TimeSpan timeout) 
            {
                bool result = true;

                if (!TimeoutHelper.WaitOne(waitHandle, timeout, false)) 
                {
                    if (!parent.RemoveWaiter(this)) 
                    { 
                        waitHandle.WaitOne();
                    } 
                    else
                    {
                        result = false;
                    } 
                }
 
                waitHandle.Close(); 
                if (this.aborted)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ThreadNeutralSemaphore.CreateObjectAbortedException());
                }

                return result; 
            }
 
            public override void Signal() 
            {
                waitHandle.Set(); 
            }

            public override void Abort()
            { 
                this.aborted = true;
                waitHandle.Set(); 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK