AsyncWaitHandle.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / System.Runtime.DurableInstancing / System / Runtime / AsyncWaitHandle.cs / 1305376 / AsyncWaitHandle.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.Runtime
{ 
    using System;
    using System.Collections.Generic; 
    using System.Security; 
    using System.Threading;
 
    [Fx.Tag.SynchronizationPrimitive(Fx.Tag.BlocksUsing.MonitorWait, SupportsAsync = true, ReleaseMethod = "Set")]
    class AsyncWaitHandle
    {
        static Action timerCompleteCallback; 

        List asyncWaiters; 
        bool isSignaled; 
        EventResetMode resetMode;
 
        [Fx.Tag.SynchronizationObject(Kind = Fx.Tag.SynchronizationKind.MonitorWait)]
        object syncObject;

        int syncWaiterCount; 

        public AsyncWaitHandle() 
            : this(EventResetMode.AutoReset) 
        {
        } 

        public AsyncWaitHandle(EventResetMode resetMode)
        {
            this.resetMode = resetMode; 
            this.syncObject = new object();
        } 
 
        public bool WaitAsync(Action callback, object state, TimeSpan timeout)
        { 
            if (!this.isSignaled || (this.isSignaled && this.resetMode == EventResetMode.AutoReset))
            {
                lock (syncObject)
                { 
                    if (this.isSignaled && this.resetMode == EventResetMode.AutoReset)
                    { 
                        this.isSignaled = false; 
                    }
                    else if (!this.isSignaled) 
                    {
                        AsyncWaiter waiter = new AsyncWaiter(this, callback, state);

                        if (this.asyncWaiters == null) 
                        {
                            this.asyncWaiters = new List(); 
                        } 

                        this.asyncWaiters.Add(waiter); 

                        if (timeout != TimeSpan.MaxValue)
                        {
                            if (timerCompleteCallback == null) 
                            {
                                timerCompleteCallback = new Action(OnTimerComplete); 
                            } 
                            waiter.SetTimer(timerCompleteCallback, waiter, timeout);
                        } 
                        return false;
                    }
                }
            } 

            return true; 
        } 

        static void OnTimerComplete(object state) 
        {
            AsyncWaiter waiter = (AsyncWaiter)state;
            AsyncWaitHandle thisPtr = waiter.Parent;
            bool callWaiter = false; 

            lock (thisPtr.syncObject) 
            { 
                // If still in the waiting list (that means it hasn't been signaled)
                if (thisPtr.asyncWaiters != null && thisPtr.asyncWaiters.Remove(waiter)) 
                {
                    waiter.TimedOut = true;
                    callWaiter = true;
                } 
            }
 
            waiter.CancelTimer(); 

            if (callWaiter) 
            {
                waiter.Call();
            }
        } 

        [Fx.Tag.Blocking] 
        public bool Wait(TimeSpan timeout) 
        {
            if (!this.isSignaled || (this.isSignaled && this.resetMode == EventResetMode.AutoReset)) 
            {
                lock (syncObject)
                {
                    if (this.isSignaled && this.resetMode == EventResetMode.AutoReset) 
                    {
                        this.isSignaled = false; 
                    } 
                    else if (!this.isSignaled)
                    { 
                        bool decrementRequired = false;

                        try
                        { 
                            try
                            { 
                            } 
                            finally
                            { 
                                this.syncWaiterCount++;
                                decrementRequired = true;
                            }
 
                            if (timeout == TimeSpan.MaxValue)
                            { 
                                if (!Monitor.Wait(syncObject, Timeout.Infinite)) 
                                {
                                    return false; 
                                }
                            }
                            else
                            { 
                                if (!Monitor.Wait(syncObject, timeout))
                                { 
                                    return false; 
                                }
                            } 
                        }
                        finally
                        {
                            if (decrementRequired) 
                            {
                                this.syncWaiterCount--; 
                            } 
                        }
                    } 
                }
            }

            return true; 
        }
 
        public void Set() 
        {
            List toCallList = null; 
            AsyncWaiter toCall = null;

            if (!this.isSignaled)
            { 
                lock (syncObject)
                { 
                    if (!this.isSignaled) 
                    {
                        if (this.resetMode == EventResetMode.ManualReset) 
                        {
                            this.isSignaled = true;
                            Monitor.PulseAll(syncObject);
                            toCallList = this.asyncWaiters; 
                            this.asyncWaiters = null;
                        } 
                        else 
                        {
                            if (this.syncWaiterCount > 0) 
                            {
                                Monitor.Pulse(syncObject);
                            }
                            else if (this.asyncWaiters != null && this.asyncWaiters.Count > 0) 
                            {
                                toCall = this.asyncWaiters[0]; 
                                this.asyncWaiters.RemoveAt(0); 
                            }
                            else 
                            {
                                this.isSignaled = true;
                            }
                        } 
                    }
                } 
            } 

            if (toCallList != null) 
            {
                foreach (AsyncWaiter waiter in toCallList)
                {
                    waiter.CancelTimer(); 
                    waiter.Call();
                } 
            } 

            if (toCall != null) 
            {
                toCall.CancelTimer();
                toCall.Call();
            } 
        }
 
        public void Reset() 
        {
            // Doesn't matter if this changes during processing of another method 
            this.isSignaled = false;
        }

        class AsyncWaiter : ActionItem 
        {
            [Fx.Tag.SecurityNote(Critical = "Store the delegate to be invoked")] 
            [SecurityCritical] 
            Action callback;
            [Fx.Tag.SecurityNote(Critical = "Stores the state object to be passed to the callback")] 
            [SecurityCritical]
            object state;
            IOThreadTimer timer;
            TimeSpan originalTimeout; 

            [Fx.Tag.SecurityNote(Critical = "Access critical members", Safe="Doesn't leak information")] 
            [SecuritySafeCritical] 
            public AsyncWaiter(AsyncWaitHandle parent, Action callback, object state)
            { 
                this.Parent = parent;
                this.callback = callback;
                this.state = state;
            } 

            public AsyncWaitHandle Parent 
            { 
                get;
                private set; 
            }

            public bool TimedOut
            { 
                get;
                set; 
            } 

            [Fx.Tag.SecurityNote(Critical = "Calls into critical method Schedule", Safe = "Invokes the given delegate under the current context")] 
            [SecuritySafeCritical]
            public void Call()
            {
                Schedule(); 
            }
 
            [Fx.Tag.SecurityNote(Critical = "Overriding an inherited critical method, access critical members")] 
            [SecurityCritical]
            protected override void Invoke() 
            {
                this.callback(this.state,
                    this.TimedOut ? new TimeoutException(SRCore.TimeoutOnOperation(this.originalTimeout)) : null);
            } 

            public void SetTimer(Action callback, object state, TimeSpan timeout) 
            { 
                if (this.timer != null)
                { 
                    throw Fx.Exception.AsError(new InvalidOperationException(SRCore.MustCancelOldTimer));
                }

                this.originalTimeout = timeout; 
                this.timer = new IOThreadTimer(callback, state, false);
 
                this.timer.Set(timeout); 
            }
 
            public void CancelTimer()
            {
                if (this.timer != null)
                { 
                    this.timer.Cancel();
                    this.timer = null; 
                } 
            }
        } 
    }

}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

                        

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