ConcurrencyBehavior.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 / Dispatcher / ConcurrencyBehavior.cs / 1 / ConcurrencyBehavior.cs

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

namespace System.ServiceModel.Dispatcher 
{
    using System; 
    using System.ServiceModel; 
    using System.ServiceModel.Channels;
    using System.Threading; 
    using System.Collections.Generic;

    class ConcurrencyBehavior
    { 
        ConcurrencyMode mode;
        bool supportsTransactedBatch; 
 
        internal ConcurrencyBehavior(DispatchRuntime runtime)
        { 
            this.mode = runtime.ConcurrencyMode;
            this.supportsTransactedBatch = ConcurrencyBehavior.SupportsTransactedBatch(runtime.ChannelDispatcher);
        }
 
        static bool SupportsTransactedBatch(ChannelDispatcher channelDispatcher)
        { 
            return channelDispatcher.IsTransactedReceive && (channelDispatcher.MaxTransactedBatchSize > 0); 
        }
 
        internal bool IsConcurrent(ref MessageRpc rpc)
        {
            return IsConcurrent(this.mode, rpc.Channel.HasSession, this.supportsTransactedBatch);
        } 

        internal static bool IsConcurrent(ConcurrencyMode mode, bool hasSession, bool supportsTransactedBatch) 
        { 
            return !supportsTransactedBatch && ((mode != ConcurrencyMode.Single) || !hasSession);
        } 

        internal static bool IsConcurrent(ChannelDispatcher runtime, bool hasSession)
        {
            if (ConcurrencyBehavior.SupportsTransactedBatch(runtime)) 
            {
                return false; 
            } 

            if (!hasSession) 
            {
                return true;
            }
 
            foreach (EndpointDispatcher endpointDispatcher in runtime.Endpoints)
            { 
                if (endpointDispatcher.DispatchRuntime.ConcurrencyMode != ConcurrencyMode.Single) 
                {
                    return true; 
                }
            }
            return false;
        } 

        internal void LockInstance(ref MessageRpc rpc) 
        { 
            if (this.mode != ConcurrencyMode.Multiple)
            { 
                ConcurrencyInstanceContextFacet resource = rpc.InstanceContext.Concurrency;
                lock (rpc.InstanceContext.ThisLock)
                {
                    if (!resource.Locked) 
                    {
                        resource.Locked = true; 
                    } 
                    else
                    { 
                        MessageRpcWaiter waiter = new MessageRpcWaiter(rpc.Pause());
                        resource.EnqueueNewMessage(waiter);
                    }
                } 

                if (this.mode == ConcurrencyMode.Reentrant) 
                { 
                    rpc.OperationContext.IsServiceReentrant = true;
                } 
            }
        }

        internal void UnlockInstance(ref MessageRpc rpc) 
        {
            if (this.mode != ConcurrencyMode.Multiple) 
            { 
                ConcurrencyBehavior.UnlockInstance(rpc.InstanceContext);
            } 
        }

        internal static void UnlockInstanceBeforeCallout(OperationContext operationContext)
        { 
            if (operationContext != null && operationContext.IsServiceReentrant)
            { 
                ConcurrencyBehavior.UnlockInstance(operationContext.InstanceContext); 
            }
        } 

        static void UnlockInstance(InstanceContext instanceContext)
        {
            ConcurrencyInstanceContextFacet resource = instanceContext.Concurrency; 

            lock (instanceContext.ThisLock) 
            { 
                if (resource.HasWaiters)
                { 
                    IWaiter nextWaiter = resource.DequeueWaiter();
                    nextWaiter.Signal();
                }
                else 
                {
                    //We have no pending Callouts and no new Messages to process 
                    resource.Locked = false; 
                }
            } 
        }

        internal static void LockInstanceAfterCallout(OperationContext operationContext)
        { 
            if (operationContext != null)
            { 
                InstanceContext instanceContext = operationContext.InstanceContext; 

                if (operationContext.IsServiceReentrant) 
                {
                    ConcurrencyInstanceContextFacet resource = instanceContext.Concurrency;
                    ThreadWaiter waiter = null;
 
                    lock (instanceContext.ThisLock)
                    { 
                        if (!resource.Locked) 
                        {
                            resource.Locked = true; 
                        }
                        else
                        {
                            waiter = new ThreadWaiter(); 
                            resource.EnqueueCalloutMessage(waiter);
                        } 
                    } 

                    if (waiter != null) 
                    {
                        waiter.Wait();
                    }
                } 
            }
        } 
 
        internal interface IWaiter
        { 
            void Signal();
        }

        class MessageRpcWaiter : IWaiter 
        {
            IResumeMessageRpc resume; 
 
            internal MessageRpcWaiter(IResumeMessageRpc resume)
            { 
                this.resume = resume;
            }

            void IWaiter.Signal() 
            {
                try 
                { 
                    bool alreadyResumedNoLock;
                    this.resume.Resume(out alreadyResumedNoLock); 

                    if (alreadyResumedNoLock)
                    {
                        DiagnosticUtility.DebugAssert("ConcurrencyBehavior resumed more than once for same call."); 
                    }
                } 
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e)) 
                    {
                        throw;
                    }
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e); 
                }
            } 
        } 

        class ThreadWaiter : IWaiter 
        {
            ManualResetEvent wait = new ManualResetEvent(false);

            void IWaiter.Signal() 
            {
                this.wait.Set(); 
            } 

            internal void Wait() 
            {
                this.wait.WaitOne();
                this.wait.Close();
            } 
        }
    } 
 
    internal class ConcurrencyInstanceContextFacet
    { 
        internal bool Locked;
        Queue calloutMessageQueue;
        Queue newMessageQueue;
 
        internal bool HasWaiters
        { 
            get 
            {
                return (((this.calloutMessageQueue != null) && (this.calloutMessageQueue.Count > 0)) || 
                        ((this.newMessageQueue != null) && (this.newMessageQueue.Count > 0)));
            }
        }
 
        ConcurrencyBehavior.IWaiter DequeueFrom(Queue queue)
        { 
            ConcurrencyBehavior.IWaiter waiter = queue.Dequeue(); 

            if (queue.Count == 0) 
            {
                queue.TrimExcess();
            }
 
            return waiter;
        } 
 
        internal ConcurrencyBehavior.IWaiter DequeueWaiter()
        { 
            // Finishing old work takes precedence over new work.
            if ((this.calloutMessageQueue != null) && (this.calloutMessageQueue.Count > 0))
            {
                return this.DequeueFrom(this.calloutMessageQueue); 
            }
            else 
            { 
                return this.DequeueFrom(this.newMessageQueue);
            } 
        }

        internal void EnqueueNewMessage(ConcurrencyBehavior.IWaiter waiter)
        { 
            if (this.newMessageQueue == null)
                this.newMessageQueue = new Queue(); 
            this.newMessageQueue.Enqueue(waiter); 
        }
 
        internal void EnqueueCalloutMessage(ConcurrencyBehavior.IWaiter waiter)
        {
            if (this.calloutMessageQueue == null)
                this.calloutMessageQueue = new Queue(); 
            this.calloutMessageQueue.Enqueue(waiter);
        } 
    } 
}

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