Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs33
1 files changed, 20 insertions, 13 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
index 9f27c6dcb..694514ef0 100644
--- a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
+++ b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs
@@ -19,11 +19,12 @@ using Thread = Internal.Runtime.Augments.RuntimeThread;
namespace System.Threading
{
- public delegate void ContextCallback(Object state);
+ public delegate void ContextCallback(object state);
public sealed class ExecutionContext : IDisposable, ISerializable
{
internal static readonly ExecutionContext Default = new ExecutionContext(isDefault: true);
+ internal static readonly ExecutionContext DefaultFlowSuppressed = new ExecutionContext(AsyncLocalValueMap.Empty, Array.Empty<IAsyncLocal>(), isFlowSuppressed: true);
private readonly IAsyncLocalValueMap m_localValues;
private readonly IAsyncLocal[] m_localChangeNotifications;
@@ -63,15 +64,14 @@ namespace System.Threading
{
Debug.Assert(isFlowSuppressed != m_isFlowSuppressed);
- if (!isFlowSuppressed &&
- (m_localValues == null ||
- m_localValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap))
- )
+ if (m_localValues == null || AsyncLocalValueMap.IsEmpty(m_localValues))
{
- return null; // implies the default context
+ return isFlowSuppressed ?
+ DefaultFlowSuppressed :
+ null; // implies the default context
}
- // Flow suppressing a Default context will have null values, set them to Empty
- return new ExecutionContext(m_localValues ?? AsyncLocalValueMap.Empty, m_localChangeNotifications ?? Array.Empty<IAsyncLocal>(), isFlowSuppressed);
+
+ return new ExecutionContext(m_localValues, m_localChangeNotifications, isFlowSuppressed);
}
public static AsyncFlowControl SuppressFlow()
@@ -112,7 +112,7 @@ namespace System.Threading
internal bool IsDefault => m_isDefault;
- public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state)
+ public static void Run(ExecutionContext executionContext, ContextCallback callback, object state)
{
// Note: ExecutionContext.Run is an extremely hot function and used by every await, ThreadPool execution, etc.
if (executionContext == null)
@@ -123,7 +123,7 @@ namespace System.Threading
RunInternal(executionContext, callback, state);
}
- internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
+ internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, object state)
{
// Note: ExecutionContext.RunInternal is an extremely hot function and used by every await, ThreadPool execution, etc.
// Note: Manual enregistering may be addressed by "Exception Handling Write Through Optimization"
@@ -321,19 +321,26 @@ namespace System.Threading
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);
+ newValues = current.m_localValues.Set(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
newChangeNotifications = current.m_localChangeNotifications;
}
else
{
// First AsyncLocal
- newValues = new AsyncLocalValueMap.OneElementAsyncLocalValueMap(local, newValue);
+ newValues = AsyncLocalValueMap.Create(local, newValue, treatNullValueAsNonexistent: !needChangeNotifications);
}
//
@@ -359,7 +366,7 @@ namespace System.Threading
}
Thread.CurrentThread.ExecutionContext =
- (!isFlowSuppressed && newValues.GetType() == typeof(AsyncLocalValueMap.EmptyAsyncLocalValueMap)) ?
+ (!isFlowSuppressed && AsyncLocalValueMap.IsEmpty(newValues)) ?
null : // No values, return to Default context
new ExecutionContext(newValues, newChangeNotifications, isFlowSuppressed);