Address PR feedback
authorStephen Toub <stoub@microsoft.com>
Mon, 21 Nov 2016 12:36:15 +0000 (07:36 -0500)
committerStephen Toub <stoub@microsoft.com>
Mon, 21 Nov 2016 12:36:15 +0000 (07:36 -0500)
- Delete !FEATURE_CORECLR code from ExecutionContext
- Add support for downgrading between map types when values are set to null
- Change ManyElementAsyncLocalValueMap.Set to size the dictionary based on whether the key is in the existing map

Commit migrated from https://github.com/dotnet/coreclr/commit/bc8d6117d76d6e359aaaecad99415c8d96576e3d

src/coreclr/src/mscorlib/src/System/Threading/AsyncLocal.cs
src/coreclr/src/mscorlib/src/System/Threading/ExecutionContext.cs

index e079e7b..bbfb203 100644 (file)
@@ -137,7 +137,14 @@ namespace System.Threading
         // Instance without any key/value pairs.  Used as a singleton/
         private sealed class EmptyAsyncLocalValueMap : IAsyncLocalValueMap
         {
-            public IAsyncLocalValueMap Set(IAsyncLocal key, object value) => new OneElementAsyncLocalValueMap(key, value);
+            public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
+            {
+                // If the value isn't null, then create a new one-element map to store
+                // the key/value pair.  If it is null, then we're still empty.
+                return value != null ?
+                    new OneElementAsyncLocalValueMap(key, value) :
+                    (IAsyncLocalValueMap)this;
+            }
 
             public bool TryGetValue(IAsyncLocal key, out object value)
             {
@@ -159,9 +166,23 @@ namespace System.Threading
 
             public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
             {
-                return ReferenceEquals(key, _key1) ?
-                    new OneElementAsyncLocalValueMap(key, value) :
-                    (IAsyncLocalValueMap)new TwoElementAsyncLocalValueMap(_key1, _value1, key, value);
+                if (value != null)
+                {
+                    // The value is non-null.  If the key matches one already contained in this map,
+                    // then create a new one-element map with the updated value, otherwise create
+                    // a two-element map with the additional key/value.
+                    return ReferenceEquals(key, _key1) ?
+                        new OneElementAsyncLocalValueMap(key, value) :
+                        (IAsyncLocalValueMap)new TwoElementAsyncLocalValueMap(_key1, _value1, key, value);
+                }
+                else
+                {
+                    // The value is null.  If the key exists in this map, remove it by downgrading to an empty map.
+                    // Otherwise, there's nothing to add or remove, so just return this map.
+                    return ReferenceEquals(key, _key1) ?
+                        Empty :
+                        (IAsyncLocalValueMap)this;
+                }
             }
 
             public bool TryGetValue(IAsyncLocal key, out object value)
@@ -193,10 +214,25 @@ namespace System.Threading
 
             public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
             {
-                return
-                    ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(key, value, _key2, _value2) :
-                    ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, key, value) :
-                    (IAsyncLocalValueMap)new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value);
+                if (value != null)
+                {
+                    // The value is non-null.  If the key matches one already contained in this map,
+                    // then create a new two-element map with the updated value, otherwise create
+                    // a three-element map with the additional key/value.
+                    return
+                        ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(key, value, _key2, _value2) :
+                        ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, key, value) :
+                        (IAsyncLocalValueMap)new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value);
+                }
+                else
+                {
+                    // The value is null.  If the key exists in this map, remove it by downgrading to a one-element map
+                    // without the key.  Otherwise, there's nothing to add or remove, so just return this map.
+                    return
+                        ReferenceEquals(key, _key1) ? new OneElementAsyncLocalValueMap(_key2, _value2) :
+                        ReferenceEquals(key, _key2) ? new OneElementAsyncLocalValueMap(_key1, _value1) :
+                        (IAsyncLocalValueMap)this;
+                }
             }
 
             public bool TryGetValue(IAsyncLocal key, out object value)
@@ -234,16 +270,33 @@ namespace System.Threading
 
             public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
             {
-                if (ReferenceEquals(key, _key1)) return new ThreeElementAsyncLocalValueMap(key, value, _key2, _value2, _key3, _value3);
-                if (ReferenceEquals(key, _key2)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, key, value, _key3, _value3);
-                if (ReferenceEquals(key, _key3)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value);
-
-                var multi = new MultiElementAsyncLocalValueMap(4);
-                multi.UnsafeStore(0, _key1, _value1);
-                multi.UnsafeStore(1, _key2, _value2);
-                multi.UnsafeStore(2, _key3, _value3);
-                multi.UnsafeStore(3, key, value);
-                return multi;
+                if (value != null)
+                {
+                    // The value is non-null.  If the key matches one already contained in this map,
+                    // then create a new three-element map with the updated value.
+                    if (ReferenceEquals(key, _key1)) return new ThreeElementAsyncLocalValueMap(key, value, _key2, _value2, _key3, _value3);
+                    if (ReferenceEquals(key, _key2)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, key, value, _key3, _value3);
+                    if (ReferenceEquals(key, _key3)) return new ThreeElementAsyncLocalValueMap(_key1, _value1, _key2, _value2, key, value);
+
+                    // The key doesn't exist in this map, so upgrade to a multi map that contains
+                    // the additional key/value pair.
+                    var multi = new MultiElementAsyncLocalValueMap(4);
+                    multi.UnsafeStore(0, _key1, _value1);
+                    multi.UnsafeStore(1, _key2, _value2);
+                    multi.UnsafeStore(2, _key3, _value3);
+                    multi.UnsafeStore(3, key, value);
+                    return multi;
+                }
+                else
+                {
+                    // The value is null.  If the key exists in this map, remove it by downgrading to a two-element map
+                    // without the key.  Otherwise, there's nothing to add or remove, so just return this map.
+                    return
+                        ReferenceEquals(key, _key1) ? new TwoElementAsyncLocalValueMap(_key2, _value2, _key3, _value3) :
+                        ReferenceEquals(key, _key2) ? new TwoElementAsyncLocalValueMap(_key1, _value1, _key3, _value3) :
+                        ReferenceEquals(key, _key3) ? new TwoElementAsyncLocalValueMap(_key1, _value1, _key2, _value2) :
+                        (IAsyncLocalValueMap)this;
+                }
             }
 
             public bool TryGetValue(IAsyncLocal key, out object value)
@@ -274,7 +327,7 @@ namespace System.Threading
         // Instance with up to 16 key/value pairs.
         private sealed class MultiElementAsyncLocalValueMap : IAsyncLocalValueMap
         {
-            private const int MaxMultiElements = 16;
+            internal const int MaxMultiElements = 16;
             private readonly KeyValuePair<IAsyncLocal, object>[] _keyValues;
 
             internal MultiElementAsyncLocalValueMap(int count)
@@ -291,17 +344,52 @@ namespace System.Threading
 
             public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
             {
+                // Find the key in this map.
                 for (int i = 0; i < _keyValues.Length; i++)
                 {
                     if (ReferenceEquals(key, _keyValues[i].Key))
                     {
-                        var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length);
-                        Array.Copy(_keyValues, 0, multi._keyValues, 0, _keyValues.Length);
-                        multi._keyValues[i] = new KeyValuePair<IAsyncLocal, object>(key, value);
-                        return multi;
+                        // The key is in the map.  If the value isn't null, then create a new map of the same
+                        // size that has all of the same pairs, with this new key/value pair overwriting the old.
+                        if (value != null)
+                        {
+                            var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length);
+                            Array.Copy(_keyValues, 0, multi._keyValues, 0, _keyValues.Length);
+                            multi._keyValues[i] = new KeyValuePair<IAsyncLocal, object>(key, value);
+                            return multi;
+                        }
+                        else if (_keyValues.Length == 4)
+                        {
+                            // The value is null, and we only have four elements, one of which we're removing,
+                            // so downgrade to a three-element map, without the matching element.
+                            return
+                                i == 0 ? new ThreeElementAsyncLocalValueMap(_keyValues[1].Key, _keyValues[1].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) :
+                                i == 1 ? new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[2].Key, _keyValues[2].Value, _keyValues[3].Key, _keyValues[3].Value) :
+                                i == 2 ? new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[1].Key, _keyValues[1].Value, _keyValues[3].Key, _keyValues[3].Value) :
+                                (IAsyncLocalValueMap)new ThreeElementAsyncLocalValueMap(_keyValues[0].Key, _keyValues[0].Value, _keyValues[1].Key, _keyValues[1].Value, _keyValues[2].Key, _keyValues[2].Value);
+                        }
+                        else
+                        {
+                            // The value is null, and we have enough elements remaining to warrant a multi map.
+                            // Create a new one and copy all of the elements from this one, except the one to be removed.
+                            var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length - 1);
+                            if (i != 0) Array.Copy(_keyValues, 0, multi._keyValues, 0, i);
+                            if (i != _keyValues.Length - 1) Array.Copy(_keyValues, i + 1, multi._keyValues, i, _keyValues.Length - i - 1);
+                            return multi;
+                        }
                     }
                 }
 
+                // The key does not already exist in this map.
+
+                // If the value is null, then we can simply return this same map, as there's nothing to add or remove.
+                if (value == null)
+                {
+                    return this;
+                }
+
+                // We need to create a new map that has the additional key/value pair.
+                // If with the addition we can still fit in a multi map, create one.
                 if (_keyValues.Length < MaxMultiElements)
                 {
                     var multi = new MultiElementAsyncLocalValueMap(_keyValues.Length + 1);
@@ -310,6 +398,7 @@ namespace System.Threading
                     return multi;
                 }
 
+                // Otherwise, upgrade to a many map.
                 var many = new ManyElementAsyncLocalValueMap(MaxMultiElements + 1);
                 foreach (KeyValuePair<IAsyncLocal, object> pair in _keyValues)
                 {
@@ -341,13 +430,64 @@ namespace System.Threading
 
             public IAsyncLocalValueMap Set(IAsyncLocal key, object value)
             {
-                var map = new ManyElementAsyncLocalValueMap(Count);
-                foreach (KeyValuePair<IAsyncLocal,object> pair in this)
+                int count = Count;
+                bool containsKey = ContainsKey(key);
+
+                // If the value being set exists, create a new many map, copy all of the elements from this one,
+                // and then store the new key/value pair into it.  This is the most common case.
+                if (value != null)
                 {
-                    map[pair.Key] = pair.Value;
+                    var map = new ManyElementAsyncLocalValueMap(count + (containsKey ? 0 : 1));
+                    foreach (KeyValuePair<IAsyncLocal, object> pair in this)
+                    {
+                        map[pair.Key] = pair.Value;
+                    }
+                    map[key] = value;
+                    return map;
                 }
-                map[key] = value;
-                return map;
+
+                // Otherwise, the value is null, which means null is being stored into an AsyncLocal.Value.
+                // Since there's no observable difference at the API level between storing null and the key
+                // not existing at all, we can downgrade to a smaller map rather than storing null.
+
+                // If the key is contained in this map, we're going to create a new map that's one pair smaller.
+                if (containsKey)
+                {
+                    // If the new count would be within range of a multi map instead of a many map,
+                    // downgrade to the many map, which uses less memory and is faster to access.
+                    // Otherwise, just create a new many map that's missing this key.
+                    if (count == MultiElementAsyncLocalValueMap.MaxMultiElements + 1)
+                    {
+                        var multi = new MultiElementAsyncLocalValueMap(MultiElementAsyncLocalValueMap.MaxMultiElements);
+                        int index = 0;
+                        foreach (KeyValuePair<IAsyncLocal, object> pair in this)
+                        {
+                            if (!ReferenceEquals(key, pair.Key))
+                            {
+                                multi.UnsafeStore(index++, pair.Key, pair.Value);
+                            }
+                        }
+                        Contract.Assert(index == MultiElementAsyncLocalValueMap.MaxMultiElements);
+                        return multi;
+                    }
+                    else
+                    {
+                        var map = new ManyElementAsyncLocalValueMap(count - 1);
+                        foreach (KeyValuePair<IAsyncLocal, object> pair in this)
+                        {
+                            if (!ReferenceEquals(key, pair.Key))
+                            {
+                                map[pair.Key] = pair.Value;
+                            }
+                        }
+                        Contract.Assert(map.Count == count - 1);
+                        return map;
+                    }
+                }
+
+                // We were storing null, but the key wasn't in the map, so there's nothing to change.
+                // Just return this instance.
+                return this;
             }
         }
     }
index b7c0e47..7adfca8 100644 (file)
@@ -14,32 +14,22 @@ namespace System.Threading
     using System;
     using System.Security;
     using System.Runtime.Remoting;
-#if FEATURE_IMPERSONATION
-    using System.Security.Principal;
-#endif
     using System.Collections;
     using System.Collections.Generic;
     using System.Reflection;
     using System.Runtime.ExceptionServices;
     using System.Runtime.Serialization;
     using System.Security.Permissions;
-#if FEATURE_REMOTING
-    using System.Runtime.Remoting.Messaging;
-#endif // FEATURE_REMOTING
     using System.Runtime.InteropServices;
     using System.Runtime.CompilerServices;
     using System.Runtime.ConstrainedExecution;
     using System.Diagnostics.Contracts;
     using System.Diagnostics.CodeAnalysis;
 
-#if FEATURE_CORECLR
     [System.Security.SecurityCritical] // auto-generated
-#endif
     [System.Runtime.InteropServices.ComVisible(true)]
     public delegate void ContextCallback(Object state);
 
-#if FEATURE_CORECLR
-
     [SecurityCritical]
     internal struct ExecutionContextSwitcher
     {
@@ -451,1082 +441,6 @@ namespace System.Threading
             return !(a == b);
         }
     }
-
-#else // FEATURE_CORECLR
-
-    // Legacy desktop ExecutionContext implementation
-
-    internal struct ExecutionContextSwitcher
-    {
-        internal ExecutionContext.Reader outerEC; // previous EC we need to restore on Undo
-        internal bool outerECBelongsToScope;
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        internal SecurityContextSwitcher scsw;
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        internal Object hecsw;
-#if FEATURE_IMPERSONATION
-        internal WindowsIdentity wi;
-        internal bool cachedAlwaysFlowImpersonationPolicy;
-        internal bool wiIsValid;
-#endif
-        internal Thread thread;
-
-        [System.Security.SecurityCritical]  // auto-generated
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
-#if FEATURE_CORRUPTING_EXCEPTIONS
-        [HandleProcessCorruptedStateExceptions]
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-        internal bool UndoNoThrow(Thread currentThread)
-        {
-            try
-            {
-                Undo(currentThread);
-            }
-            catch
-            {
-                return false;
-            }
-            return true;
-        }
-        
-        [System.Security.SecurityCritical]  // auto-generated
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
-        internal void Undo(Thread currentThread)
-        {
-            //
-            // Don't use an uninitialized switcher, or one that's already been used.
-            //
-            if (thread == null)
-                return; // Don't do anything
-
-            Contract.Assert(Thread.CurrentThread == this.thread);
-
-            // 
-            // Restore the HostExecutionContext before restoring the ExecutionContext.
-            //
-#if FEATURE_CAS_POLICY
-            if (hecsw != null)
-                HostExecutionContextSwitcher.Undo(hecsw);
-#endif // FEATURE_CAS_POLICY
-
-            //
-            // restore the saved Execution Context.  Note that this will also restore the 
-            // SynchronizationContext, Logical/IllogicalCallContext, etc.
-            //
-            ExecutionContext.Reader innerEC = currentThread.GetExecutionContextReader();
-            currentThread.SetExecutionContext(outerEC, outerECBelongsToScope);
-
-#if DEBUG
-            try
-            {
-                currentThread.ForbidExecutionContextMutation = true;
-#endif
-
-                //
-                // Tell the SecurityContext to do the side-effects of restoration.
-                //
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-                if (scsw.currSC != null)
-                {
-                    // Any critical failure inside scsw will cause FailFast
-                    scsw.Undo();
-                }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-
-#if FEATURE_IMPERSONATION
-                if (wiIsValid)
-                    SecurityContext.RestoreCurrentWI(outerEC, innerEC, wi, cachedAlwaysFlowImpersonationPolicy);
-#endif
-
-                thread = null; // this will prevent the switcher object being used again
-#if DEBUG
-            }
-            finally
-            {
-                currentThread.ForbidExecutionContextMutation = false;
-            }
-#endif
-            ExecutionContext.OnAsyncLocalContextChanged(innerEC.DangerousGetRawExecutionContext(), outerEC.DangerousGetRawExecutionContext());
-        }
-    }
-
-
-    public struct AsyncFlowControl: IDisposable
-    {
-        private bool useEC;
-        private ExecutionContext _ec;
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        private SecurityContext _sc;
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        private Thread _thread;
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        [SecurityCritical]
-        internal void Setup(SecurityContextDisableFlow flags)
-        {
-            useEC = false;
-            Thread currentThread = Thread.CurrentThread;
-            _sc = currentThread.GetMutableExecutionContext().SecurityContext;
-            _sc._disableFlow = flags;
-            _thread = currentThread;
-        }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        [SecurityCritical]
-        internal void Setup()
-        {
-            useEC = true;
-            Thread currentThread = Thread.CurrentThread;
-            _ec = currentThread.GetMutableExecutionContext();
-            _ec.isFlowSuppressed = true;
-            _thread = currentThread;
-        }
-        
-        public void Dispose()
-        {
-            Undo();
-        }
-        
-        [SecuritySafeCritical]
-        public void Undo()
-        {
-            if (_thread == null)
-            {
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCMultiple"));
-            }  
-            if (_thread != Thread.CurrentThread)
-            {
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCOtherThread"));
-            }
-            if (useEC) 
-            {
-                if (Thread.CurrentThread.GetMutableExecutionContext() != _ec)
-                {
-                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch"));
-                }      
-                ExecutionContext.RestoreFlow();
-            }
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            else
-            {
-                if (!Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(_sc))
-                {
-                    throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch"));
-                }      
-                SecurityContext.RestoreFlow();
-            }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK            
-            _thread = null;
-        }
-        
-        public override int GetHashCode()
-        {
-            return _thread == null ? ToString().GetHashCode() : _thread.GetHashCode();
-        }
-        
-        public override bool Equals(Object obj)
-        {
-            if (obj is AsyncFlowControl)
-                return Equals((AsyncFlowControl)obj);
-            else
-                return false;
-        }
-    
-        public bool Equals(AsyncFlowControl obj)
-        {
-            return obj.useEC == useEC && obj._ec == _ec &&
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-                obj._sc == _sc && 
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-                obj._thread == _thread;
-        }
-    
-        public static bool operator ==(AsyncFlowControl a, AsyncFlowControl b)
-        {
-            return a.Equals(b);
-        }
-        
-        public static bool operator !=(AsyncFlowControl a, AsyncFlowControl b)
-        {
-            return !(a == b);
-        }
-        
-    }
-    
-
-#if FEATURE_SERIALIZATION
-    [Serializable]
-#endif
-    public sealed class ExecutionContext : IDisposable, ISerializable
-    {
-        /*=========================================================================
-        ** Data accessed from managed code that needs to be defined in 
-        ** ExecutionContextObject  to maintain alignment between the two classes.
-        ** DON'T CHANGE THESE UNLESS YOU MODIFY ExecutionContextObject in vm\object.h
-        =========================================================================*/
-#if FEATURE_CAS_POLICY
-        private HostExecutionContext _hostExecutionContext;
-#endif // FEATURE_CAS_POLICY
-        private SynchronizationContext _syncContext;
-        private SynchronizationContext _syncContextNoFlow;
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        private SecurityContext     _securityContext;
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-#if FEATURE_REMOTING
-        [System.Security.SecurityCritical] // auto-generated
-        private LogicalCallContext  _logicalCallContext;
-        private IllogicalCallContext _illogicalCallContext;  // this call context follows the physical thread
-#endif // #if FEATURE_REMOTING
-
-        enum Flags
-        {
-            None = 0x0,
-            IsNewCapture = 0x1,
-            IsFlowSuppressed = 0x2,
-            IsPreAllocatedDefault = 0x4
-        }
-        private Flags _flags;
-
-        private IAsyncLocalValueMap _localValues;
-        private List<IAsyncLocal> _localChangeNotifications;
-
-        internal bool isNewCapture 
-        { 
-            get
-            { 
-                return (_flags & (Flags.IsNewCapture | Flags.IsPreAllocatedDefault)) != Flags.None; 
-            }
-            set
-            {
-                Contract.Assert(!IsPreAllocatedDefault);
-                if (value)
-                    _flags |= Flags.IsNewCapture;
-                else
-                    _flags &= ~Flags.IsNewCapture;
-            }
-        }
-        internal bool isFlowSuppressed 
-        { 
-            get 
-            { 
-                return (_flags & Flags.IsFlowSuppressed) != Flags.None; 
-            }
-            set
-            {
-                Contract.Assert(!IsPreAllocatedDefault);
-                if (value)
-                    _flags |= Flags.IsFlowSuppressed;
-                else
-                    _flags &= ~Flags.IsFlowSuppressed;
-            }
-        }
-       
-
-        private static readonly ExecutionContext s_dummyDefaultEC = new ExecutionContext(isPreAllocatedDefault: true);
-
-        static internal ExecutionContext PreAllocatedDefault
-        {
-            [SecuritySafeCritical]
-            get { return s_dummyDefaultEC; }
-        }
-
-        internal bool IsPreAllocatedDefault
-        {
-            get
-            {
-                // we use _flags instead of a direct comparison w/ s_dummyDefaultEC to avoid the static access on 
-                // hot code paths.
-                if ((_flags & Flags.IsPreAllocatedDefault) != Flags.None)
-                {
-                    Contract.Assert(this == s_dummyDefaultEC);
-                    return true;
-                }
-                else
-                {
-                    return false;
-                }
-            }
-        }
-
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-        internal ExecutionContext()
-        {            
-        }
-
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-        internal ExecutionContext(bool isPreAllocatedDefault)
-        {
-            if (isPreAllocatedDefault)
-                _flags = Flags.IsPreAllocatedDefault;
-        }
-
-        // Read-only wrapper around ExecutionContext.  This enables safe reading of an ExecutionContext without accidentally modifying it.
-        internal struct Reader
-        {
-            ExecutionContext m_ec;
-
-            public Reader(ExecutionContext ec) { m_ec = ec; }
-
-            public ExecutionContext DangerousGetRawExecutionContext() { return m_ec; }
-
-            public bool IsNull { get { return m_ec == null; } }
-            [SecurityCritical]
-            public bool IsDefaultFTContext(bool ignoreSyncCtx) { return m_ec.IsDefaultFTContext(ignoreSyncCtx); }
-            public bool IsFlowSuppressed 
-            {
-                [MethodImpl(MethodImplOptions.AggressiveInlining)]
-                get { return IsNull ? false : m_ec.isFlowSuppressed; } 
-            }
-            //public Thread Thread { get { return m_ec._thread; } }
-            public bool IsSame(ExecutionContext.Reader other) { return m_ec == other.m_ec; }
-
-            public SynchronizationContext SynchronizationContext { get { return IsNull ? null : m_ec.SynchronizationContext; } }
-            public SynchronizationContext SynchronizationContextNoFlow { get { return IsNull ? null : m_ec.SynchronizationContextNoFlow; } }
-
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            public SecurityContext.Reader SecurityContext 
-            {
-                [SecurityCritical]
-                [MethodImpl(MethodImplOptions.AggressiveInlining)]
-                get { return new SecurityContext.Reader(IsNull ? null : m_ec.SecurityContext); } 
-            }
-#endif
-
-#if FEATURE_REMOTING
-            public LogicalCallContext.Reader LogicalCallContext 
-            {
-                [SecurityCritical]
-                get { return new LogicalCallContext.Reader(IsNull ? null : m_ec.LogicalCallContext); } 
-            }
-
-            public IllogicalCallContext.Reader IllogicalCallContext 
-            {
-                [SecurityCritical]
-                get { return new IllogicalCallContext.Reader(IsNull ? null : m_ec.IllogicalCallContext); } 
-            }
-#endif
-
-            [SecurityCritical]
-            public object GetLocalValue(IAsyncLocal local)
-            {
-                if (IsNull)
-                    return null;
-
-                if (m_ec._localValues == null)
-                    return null;
-
-                object value;
-                m_ec._localValues.TryGetValue(local, out value);
-                return value;
-            }
-
-            [SecurityCritical]
-            public bool HasSameLocalValues(ExecutionContext other)
-            {
-                var thisLocalValues = IsNull ? null : m_ec._localValues;
-                var otherLocalValues = other == null ? null : other._localValues;
-                return thisLocalValues == otherLocalValues;
-            }
-
-            [SecurityCritical]
-            public bool HasLocalValues()
-            {
-                return !this.IsNull && m_ec._localValues != null;
-            }
-        }
-
-        [SecurityCritical]
-        internal static object GetLocalValue(IAsyncLocal local)
-        {
-            return Thread.CurrentThread.GetExecutionContextReader().GetLocalValue(local);
-        }
-
-        [SecurityCritical]
-        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
-        {
-            ExecutionContext current = Thread.CurrentThread.GetMutableExecutionContext();
-
-            object previousValue = null;
-            bool hadPreviousValue = current._localValues != null && current._localValues.TryGetValue(local, out previousValue);
-
-            if (previousValue == newValue)
-                return;
-
-            current._localValues = current._localValues == null ?
-                AsyncLocalValueMap.Create(local, newValue) :
-                current._localValues.Set(local, newValue);
-
-            if (needChangeNotifications)
-            {
-                if (hadPreviousValue)
-                {
-                    Contract.Assert(current._localChangeNotifications != null);
-                    Contract.Assert(current._localChangeNotifications.Contains(local));
-                }
-                else
-                {
-                    if (current._localChangeNotifications == null)
-                        current._localChangeNotifications = new List<IAsyncLocal>();
-                    else
-                        current._localChangeNotifications = new List<IAsyncLocal>(current._localChangeNotifications);
-
-                    current._localChangeNotifications.Add(local);
-                }
-
-                local.OnValueChanged(previousValue, newValue, false);
-            }
-        }
-
-        [SecurityCritical]
-        [HandleProcessCorruptedStateExceptions]
-        internal static void OnAsyncLocalContextChanged(ExecutionContext previous, ExecutionContext current)
-        {
-            List<IAsyncLocal> previousLocalChangeNotifications = (previous == null) ? null : previous._localChangeNotifications;
-            if (previousLocalChangeNotifications != null)
-            {
-                foreach (IAsyncLocal local in previousLocalChangeNotifications)
-                {
-                    object previousValue = null;
-                    if (previous != null && previous._localValues != null)
-                        previous._localValues.TryGetValue(local, out previousValue);
-
-                    object currentValue = null;
-                    if (current != null && current._localValues != null)
-                        current._localValues.TryGetValue(local, out currentValue);
-
-                    if (previousValue != currentValue)
-                        local.OnValueChanged(previousValue, currentValue, true);
-                }
-            }
-
-            List<IAsyncLocal> currentLocalChangeNotifications = (current == null) ? null : current._localChangeNotifications;
-            if (currentLocalChangeNotifications != null && currentLocalChangeNotifications != previousLocalChangeNotifications)
-            {
-                try
-                {
-                    foreach (IAsyncLocal local in currentLocalChangeNotifications)
-                    {
-                        // If the local has a value in the previous context, we already fired the event for that local
-                        // in the code above.
-                        object previousValue = null;
-                        if (previous == null ||
-                            previous._localValues == null ||
-                            !previous._localValues.TryGetValue(local, out previousValue))
-                        {
-                            object currentValue = null;
-                            if (current != null && current._localValues != null)
-                                current._localValues.TryGetValue(local, out currentValue);
-
-                            if (previousValue != currentValue)
-                                local.OnValueChanged(previousValue, currentValue, true);
-                        }
-                    }
-                }
-                catch (Exception ex)
-                {
-                    Environment.FailFast(
-                        Environment.GetResourceString("ExecutionContext_ExceptionInAsyncLocalNotification"),
-                        ex);
-                }
-            }
-        }
-
-
-#if FEATURE_REMOTING
-        internal LogicalCallContext LogicalCallContext
-        {
-            [System.Security.SecurityCritical]  // auto-generated
-            get
-            {
-                if (_logicalCallContext == null)
-                {
-                _logicalCallContext = new LogicalCallContext();
-                }
-                return _logicalCallContext;
-            }
-            [System.Security.SecurityCritical]  // auto-generated
-            set
-            {
-                Contract.Assert(this != s_dummyDefaultEC);
-                _logicalCallContext = value;
-            }
-        }
-
-        internal IllogicalCallContext IllogicalCallContext
-        {
-            get
-            {
-                if (_illogicalCallContext == null)
-                {
-                _illogicalCallContext = new IllogicalCallContext();
-                }
-                return _illogicalCallContext;
-            }
-            set
-            {
-                Contract.Assert(this != s_dummyDefaultEC);
-                _illogicalCallContext = value;
-            }
-        }
-#endif // #if FEATURE_REMOTING
-
-        internal SynchronizationContext SynchronizationContext
-        {
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-            get
-            {
-                return _syncContext;
-            }
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-            set
-            {
-                Contract.Assert(this != s_dummyDefaultEC);
-                _syncContext = value;
-            }
-        }
-
-        internal SynchronizationContext SynchronizationContextNoFlow
-        {
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-            get
-            {
-                return _syncContextNoFlow;
-            }
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-            set
-            {
-                Contract.Assert(this != s_dummyDefaultEC);
-                _syncContextNoFlow = value;
-            }
-        }
-
-#if FEATURE_CAS_POLICY
-    internal HostExecutionContext HostExecutionContext
-    {
-            get 
-            {
-                return _hostExecutionContext;
-            }
-            set 
-            {
-                Contract.Assert(this != s_dummyDefaultEC);
-                _hostExecutionContext = value;
-            }
-    }
-#endif // FEATURE_CAS_POLICY
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        internal  SecurityContext SecurityContext
-        {
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-            get
-            {
-                return _securityContext;
-            }
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
-            set
-            {
-                Contract.Assert(this != s_dummyDefaultEC);
-                        // store the new security context 
-                        _securityContext = value;
-                        // perform the reverse link too
-                        if (value != null)
-                            _securityContext.ExecutionContext = this;
-            }
-        }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-
-
-        public void Dispose()
-        {
-            if(this.IsPreAllocatedDefault)
-                return; //Do nothing if this is the default context
-#if FEATURE_CAS_POLICY
-            if (_hostExecutionContext != null)
-                _hostExecutionContext.Dispose();
-#endif // FEATURE_CAS_POLICY
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            if (_securityContext != null)
-                _securityContext.Dispose();
-#endif //FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-        }
-        
-        [DynamicSecurityMethod]
-        [System.Security.SecurityCritical]  // auto-generated_required
-        public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state)
-        {
-            if (executionContext == null)
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext"));
-            if (!executionContext.isNewCapture)
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
-            
-            Run(executionContext, callback, state, false);
-        }
-
-        // This method is special from a security perspective - the VM will not allow a stack walk to
-        // continue past the call to ExecutionContext.Run.  If you change the signature to this method, make
-        // sure to update SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new signature.
-        [DynamicSecurityMethod]
-        [SecurityCritical]
-        [FriendAccessAllowed]
-        internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx)
-        {
-            RunInternal(executionContext, callback, state, preserveSyncCtx);
-        }
-
-        // Actual implementation of Run is here, in a non-DynamicSecurityMethod, because the JIT seems to refuse to inline callees into
-        // a DynamicSecurityMethod.
-        [SecurityCritical]
-        [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
-        [HandleProcessCorruptedStateExceptions]
-        internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx)
-        {
-            Contract.Assert(executionContext != null);
-            if (executionContext.IsPreAllocatedDefault)
-            {
-                Contract.Assert(executionContext.IsDefaultFTContext(preserveSyncCtx));
-            }
-            else
-            {
-                Contract.Assert(executionContext.isNewCapture);
-                executionContext.isNewCapture = false;
-            }
-
-            Thread currentThread = Thread.CurrentThread;
-            ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher);
-
-            RuntimeHelpers.PrepareConstrainedRegions();
-            try
-            {
-                ExecutionContext.Reader ec = currentThread.GetExecutionContextReader();
-                if ( (ec.IsNull || ec.IsDefaultFTContext(preserveSyncCtx)) && 
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-                    SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) && 
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK                
-                    executionContext.IsDefaultFTContext(preserveSyncCtx) &&
-                    ec.HasSameLocalValues(executionContext)
-                    )
-                {
-                    // Neither context is interesting, so we don't need to set the context.
-                    // We do need to reset any changes made by the user's callback,
-                    // so here we establish a "copy-on-write scope".  Any changes will
-                    // result in a copy of the context being made, preserving the original
-                    // context.
-                    EstablishCopyOnWriteScope(currentThread, true, ref ecsw);
-                }
-                else
-                {
-                    if (executionContext.IsPreAllocatedDefault)
-                        executionContext = new ExecutionContext();
-                    ecsw = SetExecutionContext(executionContext, preserveSyncCtx);
-                }
-
-                //
-                // Call the user's callback
-                //
-                callback(state);
-            }
-            finally
-            {
-                ecsw.Undo(currentThread);
-            }
-        }
-
-        [SecurityCritical]
-        static internal void EstablishCopyOnWriteScope(Thread currentThread, ref ExecutionContextSwitcher ecsw)
-        {
-            EstablishCopyOnWriteScope(currentThread, false, ref ecsw);
-        }
-
-        [SecurityCritical]
-        static private void EstablishCopyOnWriteScope(Thread currentThread, bool knownNullWindowsIdentity, ref ExecutionContextSwitcher ecsw)
-        {
-            Contract.Assert(currentThread == Thread.CurrentThread);
-
-            ecsw.outerEC = currentThread.GetExecutionContextReader();
-            ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope;
-
-#if FEATURE_IMPERSONATION
-            ecsw.cachedAlwaysFlowImpersonationPolicy = SecurityContext.AlwaysFlowImpersonationPolicy;
-            if (knownNullWindowsIdentity)
-                Contract.Assert(SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy) == null);
-            else
-                ecsw.wi = SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy);
-            ecsw.wiIsValid = true;
-#endif
-            currentThread.ExecutionContextBelongsToCurrentScope = false;
-            ecsw.thread = currentThread;
-        }
-
-            
-        // Sets the given execution context object on the thread.
-        // Returns the previous one.
-        [System.Security.SecurityCritical]  // auto-generated
-        [DynamicSecurityMethodAttribute()]
-        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
-#if FEATURE_CORRUPTING_EXCEPTIONS
-        [HandleProcessCorruptedStateExceptions] 
-#endif // FEATURE_CORRUPTING_EXCEPTIONS
-        internal  static ExecutionContextSwitcher SetExecutionContext(ExecutionContext executionContext, bool preserveSyncCtx)
-        {
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-
-            Contract.Assert(executionContext != null);
-            Contract.Assert(executionContext != s_dummyDefaultEC);
-
-            // Set up the switcher object to return;
-            ExecutionContextSwitcher ecsw = new ExecutionContextSwitcher();
-            
-            Thread currentThread = Thread.CurrentThread;
-            ExecutionContext.Reader outerEC = currentThread.GetExecutionContextReader();
-
-            ecsw.thread = currentThread;
-            ecsw.outerEC = outerEC;
-            ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope;
-
-            if (preserveSyncCtx)
-                executionContext.SynchronizationContext = outerEC.SynchronizationContext;
-            executionContext.SynchronizationContextNoFlow = outerEC.SynchronizationContextNoFlow;
-
-            currentThread.SetExecutionContext(executionContext, belongsToCurrentScope: true);
-
-            RuntimeHelpers.PrepareConstrainedRegions();
-            try
-            {
-                OnAsyncLocalContextChanged(outerEC.DangerousGetRawExecutionContext(), executionContext);
-
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-                //set the security context
-                SecurityContext sc = executionContext.SecurityContext;
-                if (sc != null)
-                {
-                    // non-null SC: needs to be set
-                    SecurityContext.Reader prevSeC = outerEC.SecurityContext;
-                    ecsw.scsw = SecurityContext.SetSecurityContext(sc, prevSeC, false, ref stackMark);
-                }
-                else if (!SecurityContext.CurrentlyInDefaultFTSecurityContext(ecsw.outerEC))
-                {
-                    // null incoming SC, but we're currently not in FT: use static FTSC to set
-                    SecurityContext.Reader prevSeC = outerEC.SecurityContext;
-                    ecsw.scsw = SecurityContext.SetSecurityContext(SecurityContext.FullTrustSecurityContext, prevSeC, false, ref stackMark);
-                }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-#if FEATURE_CAS_POLICY
-                // set the Host Context
-                HostExecutionContext hostContext = executionContext.HostExecutionContext;
-                if (hostContext != null)
-                {
-                    ecsw.hecsw = HostExecutionContextManager.SetHostExecutionContextInternal(hostContext);
-                } 
-#endif // FEATURE_CAS_POLICY
-            }
-            catch
-            {
-                ecsw.UndoNoThrow(currentThread);
-                throw;
-            }
-            return ecsw;    
-        }
-
-        //
-        // Public CreateCopy.  Used to copy captured ExecutionContexts so they can be reused multiple times.
-        // This should only copy the portion of the context that we actually capture.
-        //
-        [SecuritySafeCritical]
-        public ExecutionContext CreateCopy()
-        {
-            if (!isNewCapture)
-            {
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotCopyUsedContext"));
-            }
-            ExecutionContext ec = new ExecutionContext();
-            ec.isNewCapture = true;
-            ec._syncContext = _syncContext == null ? null : _syncContext.CreateCopy();
-            ec._localValues = _localValues;
-            ec._localChangeNotifications = _localChangeNotifications;
-#if FEATURE_CAS_POLICY
-            // capture the host execution context
-            ec._hostExecutionContext = _hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy();
-#endif // FEATURE_CAS_POLICY
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            if (_securityContext != null)
-            {
-                ec._securityContext = _securityContext.CreateCopy();
-                ec._securityContext.ExecutionContext = ec;
-            }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-
-#if FEATURE_REMOTING
-            if (this._logicalCallContext != null)
-                ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone();
-
-            Contract.Assert(this._illogicalCallContext == null);
-#endif // #if FEATURE_REMOTING
-
-            return ec;
-        }
-
-        //
-        // Creates a complete copy, used for copy-on-write.
-        //
-        [SecuritySafeCritical]
-        internal ExecutionContext CreateMutableCopy()
-        {
-            Contract.Assert(!this.isNewCapture);
-
-            ExecutionContext ec = new ExecutionContext();
-
-            // We don't deep-copy the SyncCtx, since we're still in the same context after copy-on-write.
-            ec._syncContext = this._syncContext;
-            ec._syncContextNoFlow = this._syncContextNoFlow;
-
-#if FEATURE_CAS_POLICY
-            // capture the host execution context
-            ec._hostExecutionContext = this._hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy();
-#endif // FEATURE_CAS_POLICY
-
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            if (_securityContext != null)
-            {
-                ec._securityContext = this._securityContext.CreateMutableCopy();
-                ec._securityContext.ExecutionContext = ec;
-            }
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-
-#if FEATURE_REMOTING
-            if (this._logicalCallContext != null)
-                ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone();
-
-            if (this._illogicalCallContext != null)
-                ec.IllogicalCallContext = (IllogicalCallContext)this.IllogicalCallContext.CreateCopy();
-#endif // #if FEATURE_REMOTING
-
-            ec._localValues = this._localValues;
-            ec._localChangeNotifications = this._localChangeNotifications;
-            ec.isFlowSuppressed = this.isFlowSuppressed;
-
-            return ec;
-        }
-
-        [System.Security.SecurityCritical]  // auto-generated_required
-        public static AsyncFlowControl SuppressFlow()
-        {
-            if (IsFlowSuppressed())
-            {
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
-            }
-            Contract.EndContractBlock();
-            AsyncFlowControl afc = new AsyncFlowControl();
-            afc.Setup();
-            return afc;
-        }
-
-        [SecuritySafeCritical]
-        public static void RestoreFlow()
-        {
-            ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext();
-            if (!ec.isFlowSuppressed)
-            {
-                throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow"));
-            }
-            ec.isFlowSuppressed = false;
-        }
-
-        [Pure]
-        public static bool IsFlowSuppressed()
-        {
-            return Thread.CurrentThread.GetExecutionContextReader().IsFlowSuppressed;
-        }
-
-        [System.Security.SecuritySafeCritical]  // auto-generated
-        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
-        public static ExecutionContext Capture()
-        {
-            // set up a stack mark for finding the caller
-            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
-            return ExecutionContext.Capture(ref stackMark, CaptureOptions.None);            
-        }
-
-        //
-        // Captures an ExecutionContext with optimization for the "default" case, and captures a "null" synchronization context.
-        // When calling ExecutionContext.Run on the returned context, specify ignoreSyncCtx = true
-        //
-        [System.Security.SecuritySafeCritical]  // auto-generated
-        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
-        [FriendAccessAllowed]
-        internal static ExecutionContext FastCapture()
-        {
-            // set up a stack mark for finding the caller
-            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
-            return ExecutionContext.Capture(ref stackMark, CaptureOptions.IgnoreSyncCtx | CaptureOptions.OptimizeDefaultCase);
-        }
-
-
-        [Flags]
-        internal enum CaptureOptions
-        {
-            None = 0x00,
-
-            IgnoreSyncCtx = 0x01,       //Don't flow SynchronizationContext
-
-            OptimizeDefaultCase = 0x02, //Faster in the typical case, but can't show the result to users
-                                        // because they could modify the shared default EC.
-                                        // Use this only if you won't be exposing the captured EC to users.
-        }
-
-    // internal helper to capture the current execution context using a passed in stack mark
-        [System.Security.SecurityCritical]  // auto-generated
-        static internal ExecutionContext Capture(ref StackCrawlMark stackMark, CaptureOptions options)
-        {
-            ExecutionContext.Reader ecCurrent = Thread.CurrentThread.GetExecutionContextReader();
-
-            // check to see if Flow is suppressed
-            if (ecCurrent.IsFlowSuppressed) 
-                return null;
-
-            //
-            // Attempt to capture context.  There may be nothing to capture...
-            //
-
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            // capture the security context
-            SecurityContext secCtxNew = SecurityContext.Capture(ecCurrent, ref stackMark);
-#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-#if FEATURE_CAS_POLICY
-             // capture the host execution context
-            HostExecutionContext hostCtxNew = HostExecutionContextManager.CaptureHostExecutionContext();                
-#endif // FEATURE_CAS_POLICY
-
-            SynchronizationContext syncCtxNew = null;
-
-#if FEATURE_REMOTING
-            LogicalCallContext logCtxNew = null;
-#endif
-
-            if (!ecCurrent.IsNull)
-            {
-                // capture the sync context
-                if (0 == (options & CaptureOptions.IgnoreSyncCtx))
-                    syncCtxNew = (ecCurrent.SynchronizationContext == null) ? null : ecCurrent.SynchronizationContext.CreateCopy();
-
-#if FEATURE_REMOTING
-                // copy over the Logical Call Context
-                if (ecCurrent.LogicalCallContext.HasInfo)
-                    logCtxNew = ecCurrent.LogicalCallContext.Clone();
-#endif // #if FEATURE_REMOTING
-            }
-
-            IAsyncLocalValueMap localValues = null;
-            List<IAsyncLocal> localChangeNotifications = null;
-            if (!ecCurrent.IsNull)
-            {
-                localValues = ecCurrent.DangerousGetRawExecutionContext()._localValues;
-                localChangeNotifications = ecCurrent.DangerousGetRawExecutionContext()._localChangeNotifications;
-            }
-
-            //
-            // If we didn't get anything but defaults, and we're allowed to return the 
-            // dummy default EC, don't bother allocating a new context.
-            //
-            if (0 != (options & CaptureOptions.OptimizeDefaultCase) &&
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-                secCtxNew == null &&
-#endif
-#if FEATURE_CAS_POLICY
-                hostCtxNew == null &&
-#endif // FEATURE_CAS_POLICY
-                syncCtxNew == null &&
-#if FEATURE_REMOTING
-                (logCtxNew == null || !logCtxNew.HasInfo) &&
-#endif // #if FEATURE_REMOTING
-                localValues == null &&
-                localChangeNotifications == null
-                )
-            {
-                return s_dummyDefaultEC;
-            }
-
-            //
-            // Allocate the new context, and fill it in.
-            //
-            ExecutionContext ecNew = new ExecutionContext();
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            ecNew.SecurityContext = secCtxNew;
-            if (ecNew.SecurityContext != null)
-                ecNew.SecurityContext.ExecutionContext = ecNew;
-#endif
-#if FEATURE_CAS_POLICY
-            ecNew._hostExecutionContext = hostCtxNew;
-#endif // FEATURE_CAS_POLICY
-            ecNew._syncContext = syncCtxNew;
-#if FEATURE_REMOTING
-            ecNew.LogicalCallContext = logCtxNew;
-#endif // #if FEATURE_REMOTING
-            ecNew._localValues = localValues;
-            ecNew._localChangeNotifications = localChangeNotifications;
-            ecNew.isNewCapture = true;
-
-            return ecNew;
-        }
-
-        //
-        // Implementation of ISerializable
-        //
-
-        [System.Security.SecurityCritical]  // auto-generated_required
-        public void GetObjectData(SerializationInfo info, StreamingContext context)
-        {
-            if (info==null) 
-                throw new ArgumentNullException(nameof(info));
-            Contract.EndContractBlock();
-
-#if FEATURE_REMOTING
-            if (_logicalCallContext != null)
-            {
-                info.AddValue("LogicalCallContext", _logicalCallContext, typeof(LogicalCallContext));
-            }
-#endif // #if FEATURE_REMOTING
-        }
-
-        [System.Security.SecurityCritical]  // auto-generated
-        private ExecutionContext(SerializationInfo info, StreamingContext context) 
-        {
-            SerializationInfoEnumerator e = info.GetEnumerator();
-            while (e.MoveNext())
-            {
-#if FEATURE_REMOTING
-                if (e.Name.Equals("LogicalCallContext"))
-                {
-                    _logicalCallContext = (LogicalCallContext) e.Value;
-                }
-#endif // #if FEATURE_REMOTING
-            }
-        } // ObjRef .ctor
-     
-
-        [System.Security.SecurityCritical]  // auto-generated
-        internal bool IsDefaultFTContext(bool ignoreSyncCtx)
-        {
-#if FEATURE_CAS_POLICY
-            if (_hostExecutionContext != null)
-                return false;
-#endif // FEATURE_CAS_POLICY            
-            if (!ignoreSyncCtx && _syncContext != null)
-                return false;
-#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-            if (_securityContext != null && !_securityContext.IsDefaultFTSecurityContext())
-                return false;
-#endif //#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
-#if FEATURE_REMOTING
-            if (_logicalCallContext != null && _logicalCallContext.HasInfo)
-                return false;
-            if (_illogicalCallContext != null && _illogicalCallContext.HasUserData)
-                return false;
-#endif //#if FEATURE_REMOTING
-            return true;
-        }
-    } // class ExecutionContext
-
-#endif //FEATURE_CORECLR
 }