Ejemplo n.º 1
0
        private ExecutionContext?ShallowClone(bool isFlowSuppressed)
        {
            Debug.Assert(isFlowSuppressed != m_isFlowSuppressed);

            if (m_localValues == null || AsyncLocalValueMap.IsEmpty(m_localValues))
            {
                return(isFlowSuppressed ?
                       DefaultFlowSuppressed :
                       null); // implies the default context
            }

            return(new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed));
        }
Ejemplo n.º 2
0
        private ExecutionContext?ShallowClone(bool isFlowSuppressed)
        {
            Debug.Assert(isFlowSuppressed != m_isFlowSuppressed);

            if (m_localValues == null || AsyncLocalValueMap.IsEmpty(m_localValues))
            {
#pragma warning disable CA1825 // Avoid unnecessary zero-length array allocations
                return(isFlowSuppressed ?
                       (s_defaultFlowSuppressed ??= new ExecutionContext(AsyncLocalValueMap.Empty, new IAsyncLocal[0], isFlowSuppressed: true)) :
                       null); // implies the default context

#pragma warning restore CA1825
            }

            return(new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed));
        }
Ejemplo n.º 3
0
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext mutableExecutionContext = Thread.CurrentThread.GetMutableExecutionContext();
            object           obj  = null;
            bool             flag = mutableExecutionContext._localValues != null && mutableExecutionContext._localValues.TryGetValue(local, out obj);

            if (obj == newValue)
            {
                return;
            }
            IAsyncLocalValueMap asyncLocalValueMap = mutableExecutionContext._localValues;

            if (asyncLocalValueMap == null)
            {
                asyncLocalValueMap = AsyncLocalValueMap.Create(local, newValue, !needChangeNotifications);
            }
            else
            {
                asyncLocalValueMap = asyncLocalValueMap.Set(local, newValue, !needChangeNotifications);
            }
            mutableExecutionContext._localValues = asyncLocalValueMap;
            if (needChangeNotifications)
            {
                if (!flag)
                {
                    IAsyncLocal[] array = mutableExecutionContext._localChangeNotifications;
                    if (array == null)
                    {
                        array = new IAsyncLocal[]
                        {
                            local
                        };
                    }
                    else
                    {
                        int num = array.Length;
                        Array.Resize <IAsyncLocal>(ref array, num + 1);
                        array[num] = local;
                    }
                    mutableExecutionContext._localChangeNotifications = array;
                }
                local.OnValueChanged(obj, newValue, false);
            }
        }
Ejemplo n.º 4
0
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext current = Thread.CurrentThread.ExecutionContext;

            object previousValue    = null;
            bool   hadPreviousValue = false;

            if (current != null)
            {
                hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);
            }

            if (previousValue == newValue)
            {
                return;
            }

            // Regarding 'treatNullValueAsNonexistent: !needChangeNotifications' below:
            // - When change notifications are not necessary for this IAsyncLocal, there is no observable difference between
            //   storing a null value and removing the IAsyncLocal from 'm_localValues'
            // - When change notifications are necessary for this IAsyncLocal, the IAsyncLocal's absence in 'm_localValues'
            //   indicates that this is the first value change for the IAsyncLocal and it needs to be registered for change
            //   notifications. So in this case, a null value must be stored in 'm_localValues' to indicate that the IAsyncLocal
            //   is already registered for change notifications.
            IAsyncLocal[]       newChangeNotifications = null;
            IAsyncLocalValueMap newValues;
            bool isFlowSuppressed = false;

            if (current != null)
            {
                isFlowSuppressed       = current.m_isFlowSuppressed;
                newValues              = current.m_localValues.Set(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
                newChangeNotifications = current.m_localChangeNotifications;
            }
            else
            {
                // First AsyncLocal
                newValues = AsyncLocalValueMap.Create(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
            }

            //
            // Either copy the change notification array, or create a new one, depending on whether we need to add a new item.
            //
            if (needChangeNotifications)
            {
                if (hadPreviousValue)
                {
                    Debug.Assert(newChangeNotifications != null);
                    Debug.Assert(Array.IndexOf(newChangeNotifications, local) >= 0);
                }
                else if (newChangeNotifications == null)
                {
                    newChangeNotifications = new IAsyncLocal[1] {
                        local
                    };
                }
                else
                {
                    int newNotificationIndex = newChangeNotifications.Length;
                    Array.Resize(ref newChangeNotifications, newNotificationIndex + 1);
                    newChangeNotifications[newNotificationIndex] = local;
                }
            }

            Thread.CurrentThread.ExecutionContext =
                (!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
                null : // No values, return to Default context
                new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);

            if (needChangeNotifications)
            {
                local.OnValueChanged(previousValue, newValue, contextChanged: false);
            }
        }