OverlappedAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Log / System / IO / Log / OverlappedAsyncResult.cs / 1305376 / OverlappedAsyncResult.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.IO.Log
{ 
    using System;
    using System.Diagnostics; 
    using System.Runtime; 
    using System.Runtime.InteropServices;
    using System.Security.Permissions; 
    using System.Threading;
    using System.ServiceModel.Diagnostics;

    using Microsoft.Win32.SafeHandles; 

    // How to use: 
    //   1. Subclass, implement IOCompleted. 
    //   2. Call Pack() each time before invoking native method.
    //   3. Use NativeOverlapped pointer in native method 
    //   4. If call completes synchronously, Free() immediately
    //   5. If call completes asynchronously, Free() is called for you
    //
    unsafe abstract class OverlappedAsyncResult : IAsyncResult 
    {
        // Boring stuff needed to implement IAsyncResult 
        // correctly. 
        //
        object userState; 
        AsyncCallback callback;

        ManualResetEvent waitHandle;
        object syncRoot; 

        bool isCompleted; 
        bool completedSynchronously; 
        bool endCalled;
 
        Exception storedException;

        // More exciting stuff...
        // 
        NativeOverlapped* nativeOverlapped;
 
        protected OverlappedAsyncResult(AsyncCallback callback, 
                                        object state)
        { 
            this.callback = callback;
            this.userState = state;
            this.syncRoot = new Object();
 
            GC.SuppressFinalize(this);
        } 
 
        ~OverlappedAsyncResult()
        { 
            // Avoid leaking the NativeOverlapped in case things go wrong
            if (!Environment.HasShutdownStarted &&
                !AppDomain.CurrentDomain.IsFinalizingForUnload())
            { 
                Free();
            } 
        } 

        public Object AsyncState 
        {
            get { return this.userState; }
        }
 
        public WaitHandle AsyncWaitHandle
        { 
            get 
            {
                lock (this.syncRoot) 
                {
                    if (this.waitHandle == null)
                    {
                        this.waitHandle = new ManualResetEvent(this.isCompleted); 
                    }
                } 
 
                return this.waitHandle;
            } 
        }

        public bool CompletedSynchronously
        { 
            get { return this.completedSynchronously; }
        } 
 
        public bool IsCompleted
        { 
            get { return this.isCompleted; }
        }

        internal NativeOverlapped *NativeOverlapped 
        {
            get { return this.nativeOverlapped; } 
        } 

        internal void Complete(bool completedSynchronously, Exception exception) 
        {
            lock (this.syncRoot)
            {
                this.storedException = exception; 
                this.completedSynchronously = completedSynchronously;
                this.isCompleted = true; 
 
                if (this.waitHandle != null)
                    this.waitHandle.Set(); 

                Monitor.PulseAll(this.syncRoot);
            }
 
            if (this.callback != null)
            { 
                if (!completedSynchronously || 
                    !ThreadPool.QueueUserWorkItem(InvokeUserCallback, this))
                { 
                    InvokeUserCallbackFunction(this);
                }
            }
        } 

        public void End() 
        { 
            lock (this.syncRoot)
            { 
                while (!this.IsCompleted)
                {
                    Monitor.Wait(this.syncRoot);
                } 

                if (this.endCalled) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.DuplicateEnd()); 
                this.endCalled = true;
 
                if (this.storedException != null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.storedException);
                } 
           }
        } 
 
        internal void Free()
        { 
            if (this.nativeOverlapped != null)
            {
                GC.SuppressFinalize(this);
                Overlapped.Free(this.nativeOverlapped); 
                this.nativeOverlapped = null;
            } 
        } 

        internal void Pack(object pinnedObjects) 
        {
            if (this.nativeOverlapped != null)
            {
                // If we reach this condition, we have a bug in a derived AsyncResult class. 
                // It attempted to initiate a new async I/O operation before the previous
                // one completed. This is a fatal condition, so we cannot continue execution. 
                DiagnosticUtility.FailFast("Must allow previous I/O to complete before packing"); 
            }
 
            GC.ReRegisterForFinalize(this);

            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this);
            if (this.callback == null) 
            {
                this.nativeOverlapped = overlapped.UnsafePack( 
                    IOCompletionCallback, 
                    pinnedObjects);
            } 
            else
            {
                this.nativeOverlapped = overlapped.Pack(
                    IOCompletionCallback, 
                    pinnedObjects);
            } 
        } 

        internal abstract void IOCompleted(uint errorCode); 

        static IOCompletionCallback IOCompletionCallback = Fx.ThunkCallback(new IOCompletionCallback(CompletionCallback));

        static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) 
        {
            try 
            { 
                Overlapped overlapped = Overlapped.Unpack(nativeOverlapped);
 
                OverlappedAsyncResult result;
                result = (OverlappedAsyncResult)overlapped.AsyncResult;
                result.Free();
 
                result.IOCompleted(errorCode);
            } 
#pragma warning suppress 56500 // We will be terminating the process with any exception in this call 
            catch(Exception e)
            { 
                // The code in the try block should not throw any exceptions.
                // If an exception is caught here, IO.Log may be in an unknown state.
                // We prefer to failfast instead of risking the possibility of log corruption.
                // Any client code using IO.Log must have a recovery model that can deal 
                // with appdomain and process failures.
                DiagnosticUtility.InvokeFinalHandler(e); 
            } 
        }
 
        static WaitCallback InvokeUserCallback = Fx.ThunkCallback(new WaitCallback(InvokeUserCallbackFunction));

        static void InvokeUserCallbackFunction(
            object data) 
        {
            try 
            { 
                OverlappedAsyncResult result = (OverlappedAsyncResult)data;
                result.callback(result); 
            }
#pragma warning suppress 56500 // We will be terminating the process with any exception in this call
            catch(Exception e)
            { 
                if (Fx.IsFatal(e))
                    throw; 
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
            } 
        }
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------
namespace System.IO.Log
{ 
    using System;
    using System.Diagnostics; 
    using System.Runtime; 
    using System.Runtime.InteropServices;
    using System.Security.Permissions; 
    using System.Threading;
    using System.ServiceModel.Diagnostics;

    using Microsoft.Win32.SafeHandles; 

    // How to use: 
    //   1. Subclass, implement IOCompleted. 
    //   2. Call Pack() each time before invoking native method.
    //   3. Use NativeOverlapped pointer in native method 
    //   4. If call completes synchronously, Free() immediately
    //   5. If call completes asynchronously, Free() is called for you
    //
    unsafe abstract class OverlappedAsyncResult : IAsyncResult 
    {
        // Boring stuff needed to implement IAsyncResult 
        // correctly. 
        //
        object userState; 
        AsyncCallback callback;

        ManualResetEvent waitHandle;
        object syncRoot; 

        bool isCompleted; 
        bool completedSynchronously; 
        bool endCalled;
 
        Exception storedException;

        // More exciting stuff...
        // 
        NativeOverlapped* nativeOverlapped;
 
        protected OverlappedAsyncResult(AsyncCallback callback, 
                                        object state)
        { 
            this.callback = callback;
            this.userState = state;
            this.syncRoot = new Object();
 
            GC.SuppressFinalize(this);
        } 
 
        ~OverlappedAsyncResult()
        { 
            // Avoid leaking the NativeOverlapped in case things go wrong
            if (!Environment.HasShutdownStarted &&
                !AppDomain.CurrentDomain.IsFinalizingForUnload())
            { 
                Free();
            } 
        } 

        public Object AsyncState 
        {
            get { return this.userState; }
        }
 
        public WaitHandle AsyncWaitHandle
        { 
            get 
            {
                lock (this.syncRoot) 
                {
                    if (this.waitHandle == null)
                    {
                        this.waitHandle = new ManualResetEvent(this.isCompleted); 
                    }
                } 
 
                return this.waitHandle;
            } 
        }

        public bool CompletedSynchronously
        { 
            get { return this.completedSynchronously; }
        } 
 
        public bool IsCompleted
        { 
            get { return this.isCompleted; }
        }

        internal NativeOverlapped *NativeOverlapped 
        {
            get { return this.nativeOverlapped; } 
        } 

        internal void Complete(bool completedSynchronously, Exception exception) 
        {
            lock (this.syncRoot)
            {
                this.storedException = exception; 
                this.completedSynchronously = completedSynchronously;
                this.isCompleted = true; 
 
                if (this.waitHandle != null)
                    this.waitHandle.Set(); 

                Monitor.PulseAll(this.syncRoot);
            }
 
            if (this.callback != null)
            { 
                if (!completedSynchronously || 
                    !ThreadPool.QueueUserWorkItem(InvokeUserCallback, this))
                { 
                    InvokeUserCallbackFunction(this);
                }
            }
        } 

        public void End() 
        { 
            lock (this.syncRoot)
            { 
                while (!this.IsCompleted)
                {
                    Monitor.Wait(this.syncRoot);
                } 

                if (this.endCalled) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(Error.DuplicateEnd()); 
                this.endCalled = true;
 
                if (this.storedException != null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(this.storedException);
                } 
           }
        } 
 
        internal void Free()
        { 
            if (this.nativeOverlapped != null)
            {
                GC.SuppressFinalize(this);
                Overlapped.Free(this.nativeOverlapped); 
                this.nativeOverlapped = null;
            } 
        } 

        internal void Pack(object pinnedObjects) 
        {
            if (this.nativeOverlapped != null)
            {
                // If we reach this condition, we have a bug in a derived AsyncResult class. 
                // It attempted to initiate a new async I/O operation before the previous
                // one completed. This is a fatal condition, so we cannot continue execution. 
                DiagnosticUtility.FailFast("Must allow previous I/O to complete before packing"); 
            }
 
            GC.ReRegisterForFinalize(this);

            Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this);
            if (this.callback == null) 
            {
                this.nativeOverlapped = overlapped.UnsafePack( 
                    IOCompletionCallback, 
                    pinnedObjects);
            } 
            else
            {
                this.nativeOverlapped = overlapped.Pack(
                    IOCompletionCallback, 
                    pinnedObjects);
            } 
        } 

        internal abstract void IOCompleted(uint errorCode); 

        static IOCompletionCallback IOCompletionCallback = Fx.ThunkCallback(new IOCompletionCallback(CompletionCallback));

        static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) 
        {
            try 
            { 
                Overlapped overlapped = Overlapped.Unpack(nativeOverlapped);
 
                OverlappedAsyncResult result;
                result = (OverlappedAsyncResult)overlapped.AsyncResult;
                result.Free();
 
                result.IOCompleted(errorCode);
            } 
#pragma warning suppress 56500 // We will be terminating the process with any exception in this call 
            catch(Exception e)
            { 
                // The code in the try block should not throw any exceptions.
                // If an exception is caught here, IO.Log may be in an unknown state.
                // We prefer to failfast instead of risking the possibility of log corruption.
                // Any client code using IO.Log must have a recovery model that can deal 
                // with appdomain and process failures.
                DiagnosticUtility.InvokeFinalHandler(e); 
            } 
        }
 
        static WaitCallback InvokeUserCallback = Fx.ThunkCallback(new WaitCallback(InvokeUserCallbackFunction));

        static void InvokeUserCallbackFunction(
            object data) 
        {
            try 
            { 
                OverlappedAsyncResult result = (OverlappedAsyncResult)data;
                result.callback(result); 
            }
#pragma warning suppress 56500 // We will be terminating the process with any exception in this call
            catch(Exception e)
            { 
                if (Fx.IsFatal(e))
                    throw; 
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
            } 
        }
    }
}

// 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