// 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)
{
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)
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)
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)
// 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)
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);
return multi;
}
+ // Otherwise, upgrade to a many map.
var many = new ManyElementAsyncLocalValueMap(MaxMultiElements + 1);
foreach (KeyValuePair<IAsyncLocal, object> pair in _keyValues)
{
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;
}
}
}
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
{
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
}