File: System\ServiceModel\Channels\ChainedAsyncResult.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.ServiceModel.Channels
{
    using System.Collections.Generic;
    using System.Runtime;
    using System.ServiceModel;
 
    internal delegate IAsyncResult ChainedBeginHandler(TimeSpan timeout, AsyncCallback asyncCallback, object state);
    internal delegate void ChainedEndHandler(IAsyncResult result);
 
    class ChainedAsyncResult : AsyncResult
    {
        ChainedBeginHandler begin2;
        ChainedEndHandler end1;
        ChainedEndHandler end2;
        TimeoutHelper timeoutHelper;
        static AsyncCallback begin1Callback = Fx.ThunkCallback(new AsyncCallback(Begin1Callback));
        static AsyncCallback begin2Callback = Fx.ThunkCallback(new AsyncCallback(Begin2Callback));
 
        protected ChainedAsyncResult(TimeSpan timeout, AsyncCallback callback, object state)
            : base(callback, state)
        {
            this.timeoutHelper = new TimeoutHelper(timeout);
        }
 
        public ChainedAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ChainedBeginHandler begin1, ChainedEndHandler end1, ChainedBeginHandler begin2, ChainedEndHandler end2)
            : base(callback, state)
        {
            this.timeoutHelper = new TimeoutHelper(timeout);
            Begin(begin1, end1, begin2, end2);
        }
 
        protected void Begin(ChainedBeginHandler begin1, ChainedEndHandler end1, ChainedBeginHandler begin2, ChainedEndHandler end2)
        {
            this.end1 = end1;
            this.begin2 = begin2;
            this.end2 = end2;
 
            IAsyncResult result = begin1(this.timeoutHelper.RemainingTime(), begin1Callback, this);
            if (!result.CompletedSynchronously)
                return;
 
            if (Begin1Completed(result))
            {
                this.Complete(true);
            }
        }
 
        static void Begin1Callback(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
                return;
 
            ChainedAsyncResult thisPtr = (ChainedAsyncResult)result.AsyncState;
 
            bool completeSelf = false;
            Exception completeException = null;
 
            try
            {
                completeSelf = thisPtr.Begin1Completed(result);
            }
#pragma warning suppress 56500 // covered by FxCOP
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }
 
                completeSelf = true;
                completeException = exception;
            }
 
            if (completeSelf)
            {
                thisPtr.Complete(false, completeException);
            }
        }
 
        bool Begin1Completed(IAsyncResult result)
        {
            end1(result);
 
            result = begin2(this.timeoutHelper.RemainingTime(), begin2Callback, this);
            if (!result.CompletedSynchronously)
                return false;
 
            end2(result);
            return true;
        }
 
        static void Begin2Callback(IAsyncResult result)
        {
            if (result.CompletedSynchronously)
                return;
 
            ChainedAsyncResult thisPtr = (ChainedAsyncResult)result.AsyncState;
 
            Exception completeException = null;
 
            try
            {
                thisPtr.end2(result);
            }
#pragma warning suppress 56500 // covered by FxCOP
            catch (Exception exception)
            {
                if (Fx.IsFatal(exception))
                {
                    throw;
                }
 
                completeException = exception;
            }
 
            thisPtr.Complete(false, completeException);
        }
 
        public static void End(IAsyncResult result)
        {
            AsyncResult.End<ChainedAsyncResult>(result);
        }
    }
 
    internal class ChainedCloseAsyncResult : ChainedAsyncResult
    {
        IList<ICommunicationObject> collection;
 
        public ChainedCloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ChainedBeginHandler begin1, ChainedEndHandler end1, IList<ICommunicationObject> collection)
            : base(timeout, callback, state)
        {
            this.collection = collection;
 
            Begin(BeginClose, EndClose, begin1, end1);
        }
 
        public ChainedCloseAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ChainedBeginHandler begin1, ChainedEndHandler end1, params ICommunicationObject[] objs)
            : base(timeout, callback, state)
        {
            collection = new List<ICommunicationObject>();
            if (objs != null)
                for (int index = 0; index < objs.Length; index++)
                    if (objs[index] != null)
                        collection.Add(objs[index]);
 
            Begin(BeginClose, EndClose, begin1, end1);
        }
 
        IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CloseCollectionAsyncResult(timeout, callback, state, collection);
        }
 
        void EndClose(IAsyncResult result)
        {
            CloseCollectionAsyncResult.End((CloseCollectionAsyncResult)result);
        }
    }
 
    internal class ChainedOpenAsyncResult : ChainedAsyncResult
    {
        IList<ICommunicationObject> collection;
 
        public ChainedOpenAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ChainedBeginHandler begin1, ChainedEndHandler end1, IList<ICommunicationObject> collection)
            : base(timeout, callback, state)
        {
            this.collection = collection;
 
            Begin(begin1, end1, BeginOpen, EndOpen);
        }
 
        public ChainedOpenAsyncResult(TimeSpan timeout, AsyncCallback callback, object state, ChainedBeginHandler begin1, ChainedEndHandler end1, params ICommunicationObject[] objs)
            : base(timeout, callback, state)
        {
            collection = new List<ICommunicationObject>();
 
            for (int index = 0; index < objs.Length; index++)
                if (objs[index] != null)
                    collection.Add(objs[index]);
 
            Begin(begin1, end1, BeginOpen, EndOpen);
        }
 
        IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new OpenCollectionAsyncResult(timeout, callback, state, collection);
        }
 
        void EndOpen(IAsyncResult result)
        {
            OpenCollectionAsyncResult.End((OpenCollectionAsyncResult)result);
        }
    }
}