Exemple #1
0
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext current = t_currentMaybeNull ?? ExecutionContext.Default;

            object previousValue;
            bool   hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);

            if (previousValue == newValue)
            {
                return;
            }

            current = new ExecutionContext(current);
            current.m_localValues[local] = newValue;

            t_currentMaybeNull = current;

            if (needChangeNotifications)
            {
                if (hadPreviousValue)
                {
                    Debug.Assert(current.m_localChangeNotifications.Contains(local));
                }
                else
                {
                    current.m_localChangeNotifications.Add(local);
                }

                local.OnValueChanged(previousValue, newValue, false);
            }
        }
Exemple #2
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);
            }
        }
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext executionContext1 = Thread.CurrentThread.GetMutableExecutionContext();
            object           previousValue     = (object)null;
            bool             flag = executionContext1._localValues != null && executionContext1._localValues.TryGetValue(local, out previousValue);

            if (previousValue == newValue)
            {
                return;
            }
            if (executionContext1._localValues == null)
            {
                executionContext1._localValues = new Dictionary <IAsyncLocal, object>();
            }
            else
            {
                ExecutionContext executionContext2          = executionContext1;
                Dictionary <IAsyncLocal, object> dictionary = new Dictionary <IAsyncLocal, object>((IDictionary <IAsyncLocal, object>)executionContext2._localValues);
                executionContext2._localValues = dictionary;
            }
            executionContext1._localValues[local] = newValue;
            if (!needChangeNotifications)
            {
                return;
            }
            if (!flag)
            {
                if (executionContext1._localChangeNotifications == null)
                {
                    executionContext1._localChangeNotifications = new List <IAsyncLocal>();
                }
                else
                {
                    ExecutionContext   executionContext2 = executionContext1;
                    List <IAsyncLocal> asyncLocalList    = new List <IAsyncLocal>((IEnumerable <IAsyncLocal>)executionContext2._localChangeNotifications);
                    executionContext2._localChangeNotifications = asyncLocalList;
                }
                executionContext1._localChangeNotifications.Add(local);
            }
            local.OnValueChanged(previousValue, newValue, false);
        }
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext current = Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default;

            object previousValue;
            bool   hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);

            if (previousValue == newValue)
            {
                return;
            }

            IAsyncLocalValueMap newValues = current.m_localValues.Set(local, newValue);

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

            Thread.CurrentThread.ExecutionContext =
                new ExecutionContext(newValues, newChangeNotifications, current.m_isFlowSuppressed);

            if (needChangeNotifications)
            {
                local.OnValueChanged(previousValue, newValue, false);
            }
        }
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext current = Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default;

            object previousValue;
            bool hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);

            if (previousValue == newValue)
                return;

            IAsyncLocalValueMap newValues = current.m_localValues.Set(local, newValue);

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

            Thread.CurrentThread.ExecutionContext =
                new ExecutionContext(newValues, newChangeNotifications, current.m_isFlowSuppressed);

            if (needChangeNotifications)
            {
                local.OnValueChanged(previousValue, newValue, false);
            }
        }
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext current = t_currentMaybeNull ?? ExecutionContext.Default;

            object previousValue;
            bool hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);

            if (previousValue == newValue)
                return;

            current = new ExecutionContext(current);
            current.m_localValues[local] = newValue;

            t_currentMaybeNull = current;

            if (needChangeNotifications)
            {
                if (hadPreviousValue)
                    Contract.Assert(current.m_localChangeNotifications.Contains(local));
                else
                    current.m_localChangeNotifications.Add(local);

                local.OnValueChanged(previousValue, newValue, false);
            }
        }
        internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
        {
            ExecutionContext current = Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default;

            object previousValue;
            bool hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);

            if (previousValue == newValue)
                return;

            //
            // Allocate a new Dictionary containing a copy of the old values, plus the new value.  We have to do this manually to 
            // minimize allocations of IEnumerators, etc.
            //
            Dictionary<IAsyncLocal, object> newValues = new Dictionary<IAsyncLocal, object>(current.m_localValues.Count + (hadPreviousValue ? 0 : 1));

            foreach (KeyValuePair<IAsyncLocal, object> pair in current.m_localValues)
                newValues.Add(pair.Key, pair.Value);

            newValues[local] = newValue;

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

            Thread.CurrentThread.ExecutionContext =
                new ExecutionContext(newValues, newChangeNotifications, current.m_isFlowSuppressed);

            if (needChangeNotifications)
            {
                local.OnValueChanged(previousValue, newValue, false);
            }
        }
Exemple #8
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;
            }

            IAsyncLocal[]       newChangeNotifications = null;
            IAsyncLocalValueMap newValues;
            bool isFlowSuppressed = false;

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

            //
            // 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 && newValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap)) ?
                null : // No values, return to Default context
                new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);

            if (needChangeNotifications)
            {
                local.OnValueChanged(previousValue, newValue, contextChanged: false);
            }
        }
Exemple #9
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);
            }
        }