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

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

    static class IOThreadScheduler 
    { 
        /// 
        /// Critical - calls into critical class CriticalHelper 
        /// Safe - ensures that SecurityContext flows across the thread switch
        /// 
        [SecurityCritical, SecurityTreatAsSafe]
        public static void ScheduleCallback(WaitCallback callback, object state) 
        {
            CriticalHelper.ScheduleCallback(callback, state, true, false); 
        } 

        //  The low-pri queue is susceptable to starvation if executing codepaths are dependent on the low-pri task. 
        //  Only use the low-pri queue for new requests or similarly isolated tasks.
        //
        /// 
        /// Critical - calls into critical class CriticalHelper, doesn't flow context 
        /// 
        [SecurityCritical] 
        public static void ScheduleCallbackLowPriNoFlow(WaitCallback callback, object state) 
        {
            CriticalHelper.ScheduleCallback(callback, state, false, true); 
        }

        /// 
        /// Critical - must correctly capture SecurityContext and re-apply on callback 
        /// 
        [SecurityCritical(SecurityCriticalScope.Everything)] 
        static class CriticalHelper 
        {
            static object lockObject = new object(); 
            static bool queuedCompletion;
            static Queue workQueue = new Queue();
            static Queue lowPriQueue = new Queue();
            static ScheduledOverlapped overlapped = new ScheduledOverlapped(new WaitCallback(CompletionCallback)); 

            ///  
            /// note that in some hosts this runs without any user context on the stack 
            /// 
            static void CompletionCallback(object state) 
            {
                lock (lockObject)
                {
                    queuedCompletion = false; 
                }
 
                ThreadTrace.Trace("IOThreadScheduler.CompletionCallback"); 
                ProcessCallbacks();
            } 

            /// 
            /// note that in some hosts this runs without any user context on the stack
            ///  
            static void ProcessCallbacks()
            { 
                while (true) 
                {
                    WorkItem workItem; 

                    bool needOverlappedQueued = false;
                    try
                    { 
                        lock (lockObject)
                        { 
                            if (CriticalHelper.workQueue.Count != 0) 
                            {
                                workItem = CriticalHelper.workQueue.Dequeue(); 
                            }
                            else if (CriticalHelper.lowPriQueue.Count != 0)
                            {
                                workItem = CriticalHelper.lowPriQueue.Dequeue(); 
                            }
                            else 
                            { 
                                break;
                            } 

                            if (!queuedCompletion &&
                                (CriticalHelper.workQueue.Count > 0 || CriticalHelper.lowPriQueue.Count > 0))
                            { 
                                needOverlappedQueued = true;
                                CriticalHelper.queuedCompletion = true; 
                            } 
                        }
                    } 
                    finally
                    {
                        if (needOverlappedQueued)
                        { 
                            CriticalHelper.overlapped.Post();
                        } 
                    } 

                    workItem.Invoke(); 
                }
            }

            public static void ScheduleCallback(WaitCallback callback, object state, bool flow, bool lowPri) 
            {
                if (callback == null) 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("callback")); 

                object workItemState = state; 
                if (DiagnosticUtility.ShouldUseActivity)
                {
                    // Wrap callback's state object with TracingAsyncCallbackState to
                    // capture the current thread's ActivityID 
                    workItemState = new System.ServiceModel.Diagnostics.TraceUtility.TracingAsyncCallbackState(state);
                } 
 
                ThreadTrace.Trace("IOThreadScheduler.ScheduleCallback");
 
                WorkItem workItem = new WorkItem(callback, workItemState, flow);

                bool needOverlappedQueued = false;
                try 
                {
                    lock (lockObject) 
                    { 
                        (lowPri ? CriticalHelper.lowPriQueue : CriticalHelper.workQueue).Enqueue(workItem);
 
                        if (!queuedCompletion)
                        {
                            needOverlappedQueued = true;
                            CriticalHelper.queuedCompletion = true; 
                        }
                    } 
                } 
                finally
                { 
                    if (needOverlappedQueued)
                    {
                        CriticalHelper.overlapped.Post();
                    } 
                }
            } 
 
            class WorkItem
            { 
                static ContextCallback securityContextCallback = new ContextCallback(OnSecurityContextCallback);

                WaitCallback callback;
                object state; 
                SecurityContext context;
 
                public WorkItem(WaitCallback callback, object state, bool flow) 
                {
                    this.callback = callback; 
                    this.state = state;
                    this.context = flow ? PartialTrustHelpers.CaptureSecurityContextNoIdentityFlow() : null;
                }
 
                /// 
                /// note that in some hosts this runs without any user context on the stack 
                ///  
                public void Invoke()
                { 
                    if (this.context != null)
                    {
                        SecurityContext.Run(this.context, securityContextCallback, this);
                    } 
                    else
                    { 
                        Invoke2(); 
                    }
                } 

                static void OnSecurityContextCallback(object o)
                {
                    ((WorkItem)o).Invoke2(); 
                }
 
                ///  
                /// note that in some hosts this runs without any user context on the stack
                ///  
                void Invoke2()
                {
                    // Activity tracing may have been toggled by the user after this callback was
                    // registered (e.g. via WMI).  Do not assume that since Activity tracing is on 
                    // that the state object is of type TracingAsyncCallbackState or vice versa.
                    // Instead, try the cast using the 'as' keyword.  If cast fails, asyncState's 
                    // value will be null and the following code will run as if activity tracing 
                    // is turned off.  If it is not null, then do the appropriate action based
                    // on DiagnosticUtility.ShouldUseActivity. 
                    System.ServiceModel.Diagnostics.TraceUtility.TracingAsyncCallbackState asyncState = state as System.ServiceModel.Diagnostics.TraceUtility.TracingAsyncCallbackState;

                    if (null == asyncState)
                    { 
                        this.callback(state);
                    } 
                    else 
                    {
                        using (Activity activity = DiagnosticUtility.ShouldUseActivity ? Activity.CreateActivity(asyncState.ActivityId) : null) 
                        {
                            this.callback(asyncState.InnerState);
                        }
                    } 
                }
            } 
 
            class ScheduledOverlapped
            { 
                unsafe NativeOverlapped* nativeOverlapped;
                WaitCallback callback;

                // Since we keep this object in a static, we never need to Free the overlapped, so there's no need for a finalizer. 
                unsafe public ScheduledOverlapped(WaitCallback callback)
                { 
                    Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, null); 
                    this.nativeOverlapped = overlapped.UnsafePack(DiagnosticUtility.Utility.ThunkCallback(new IOCompletionCallback(IOCallback)), null);
                    this.callback = callback; 
                }

                unsafe void IOCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
                { 
                    callback(null);
                } 
 
                unsafe public void Post()
                { 
                    ThreadPool.UnsafeQueueNativeOverlapped(this.nativeOverlapped);
                }
            }
        } 
    }
} 

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