summaryrefslogtreecommitdiff
path: root/src/mscorlib
diff options
context:
space:
mode:
authorStephen Toub <stoub@microsoft.com>2018-05-08 01:18:44 -0400
committerJan Kotas <jkotas@microsoft.com>2018-05-07 22:18:44 -0700
commitb511ceb8a712ee3d1340ea5093b1d33e19bae696 (patch)
treeac4e8bd0441fc164d120d6e47693688f172869b6 /src/mscorlib
parentba4225e5d918f2657fbbebf18be4c7323583a8cf (diff)
downloadcoreclr-b511ceb8a712ee3d1340ea5093b1d33e19bae696.tar.gz
coreclr-b511ceb8a712ee3d1340ea5093b1d33e19bae696.tar.bz2
coreclr-b511ceb8a712ee3d1340ea5093b1d33e19bae696.zip
Remove ConcurrentDictionary from System.Private.CoreLib (#17908)
* Delete stale PRENET45 conditional code * Remove ConcurrentDictionary dependency from ConcurrentExclusiveSchedulerPair
Diffstat (limited to 'src/mscorlib')
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs80
1 files changed, 20 insertions, 60 deletions
diff --git a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
index 7d60e4ca16..9c4d16f738 100644
--- a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
@@ -14,11 +14,9 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using System.Security;
namespace System.Threading.Tasks
{
@@ -31,7 +29,7 @@ namespace System.Threading.Tasks
public class ConcurrentExclusiveSchedulerPair
{
/// <summary>A dictionary mapping thread ID to a processing mode to denote what kinds of tasks are currently being processed on this thread.</summary>
- private readonly ConcurrentDictionary<int, ProcessingMode> m_threadProcessingMapping = new ConcurrentDictionary<int, ProcessingMode>();
+ private readonly ThreadLocal<ProcessingMode> m_threadProcessingMode = new ThreadLocal<ProcessingMode>(() => ProcessingMode.NotCurrentlyProcessing);
/// <summary>The scheduler used to queue and execute "concurrent" tasks that may run concurrently with other concurrent tasks.</summary>
private readonly ConcurrentExclusiveTaskScheduler m_concurrentTaskScheduler;
/// <summary>The scheduler used to queue and execute "exclusive" tasks that must run exclusively while no other tasks for this pair are running.</summary>
@@ -65,7 +63,7 @@ namespace System.Threading.Tasks
private static Int32 DefaultMaxConcurrencyLevel { get { return Environment.ProcessorCount; } }
/// <summary>Gets the sync obj used to protect all state on this instance.</summary>
- private object ValueLock { get { return m_threadProcessingMapping; } }
+ private object ValueLock { get { return m_threadProcessingMode; } }
/// <summary>
/// Initializes the ConcurrentExclusiveSchedulerPair.
@@ -211,15 +209,17 @@ namespace System.Threading.Tasks
cs.m_completionQueued = true;
ThreadPool.QueueUserWorkItem(state =>
{
- var localCs = (CompletionState)state; // don't use 'cs', as it'll force a closure
- Debug.Assert(!localCs.Task.IsCompleted, "Completion should only happen once.");
+ var localThis = (ConcurrentExclusiveSchedulerPair)state;
+ Debug.Assert(!localThis.m_completionState.Task.IsCompleted, "Completion should only happen once.");
- var exceptions = localCs.m_exceptions;
+ List<Exception> exceptions = localThis.m_completionState.m_exceptions;
bool success = (exceptions != null && exceptions.Count > 0) ?
- localCs.TrySetException(exceptions) :
- localCs.TrySetResult(default(VoidTaskResult));
+ localThis.m_completionState.TrySetException(exceptions) :
+ localThis.m_completionState.TrySetResult(default);
Debug.Assert(success, "Expected to complete completion task.");
- }, cs);
+
+ localThis.m_threadProcessingMode.Dispose();
+ }, this);
}
}
@@ -350,9 +350,9 @@ namespace System.Threading.Tasks
try
{
// Note that we're processing exclusive tasks on the current thread
- Debug.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId),
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.NotCurrentlyProcessing,
"This thread should not yet be involved in this pair's processing.");
- m_threadProcessingMapping[Thread.CurrentThread.ManagedThreadId] = ProcessingMode.ProcessingExclusiveTask;
+ m_threadProcessingMode.Value = ProcessingMode.ProcessingExclusiveTask;
// Process up to the maximum number of items per task allowed
for (int i = 0; i < m_maxItemsPerTask; i++)
@@ -369,10 +369,8 @@ namespace System.Threading.Tasks
finally
{
// We're no longer processing exclusive tasks on the current thread
- ProcessingMode currentMode;
- m_threadProcessingMapping.TryRemove(Thread.CurrentThread.ManagedThreadId, out currentMode);
- Debug.Assert(currentMode == ProcessingMode.ProcessingExclusiveTask,
- "Somehow we ended up escaping exclusive mode.");
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.ProcessingExclusiveTask, "Somehow we ended up escaping exclusive mode.");
+ m_threadProcessingMode.Value = ProcessingMode.NotCurrentlyProcessing;
lock (ValueLock)
{
@@ -399,9 +397,9 @@ namespace System.Threading.Tasks
try
{
// Note that we're processing concurrent tasks on the current thread
- Debug.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId),
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.NotCurrentlyProcessing,
"This thread should not yet be involved in this pair's processing.");
- m_threadProcessingMapping[Thread.CurrentThread.ManagedThreadId] = ProcessingMode.ProcessingConcurrentTasks;
+ m_threadProcessingMode.Value = ProcessingMode.ProcessingConcurrentTasks;
// Process up to the maximum number of items per task allowed
for (int i = 0; i < m_maxItemsPerTask; i++)
@@ -429,10 +427,8 @@ namespace System.Threading.Tasks
finally
{
// We're no longer processing concurrent tasks on the current thread
- ProcessingMode currentMode;
- m_threadProcessingMapping.TryRemove(Thread.CurrentThread.ManagedThreadId, out currentMode);
- Debug.Assert(currentMode == ProcessingMode.ProcessingConcurrentTasks,
- "Somehow we ended up escaping concurrent mode.");
+ Debug.Assert(m_threadProcessingMode.Value == ProcessingMode.ProcessingConcurrentTasks, "Somehow we ended up escaping concurrent mode.");
+ m_threadProcessingMode.Value = ProcessingMode.NotCurrentlyProcessing;
lock (ValueLock)
{
@@ -448,17 +444,6 @@ namespace System.Threading.Tasks
}
}
-#if PRENET45
- /// <summary>
- /// Type used with TaskCompletionSource(Of TResult) as the TResult
- /// to ensure that the resulting task can't be upcast to something
- /// that in the future could lead to compat problems.
- /// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
- [DebuggerNonUserCode]
- private struct VoidTaskResult { }
-#endif
-
/// <summary>
/// Holder for lazily-initialized state about the completion of a scheduler pair.
/// Completion is only triggered either by rare exceptional conditions or by
@@ -580,9 +565,7 @@ namespace System.Threading.Tasks
// If a task is already running on this thread, allow inline execution to proceed.
// If there's already a task from this scheduler running on the current thread, we know it's safe
// to run this task, in effect temporarily taking that task's count allocation.
- ProcessingMode currentThreadMode;
- if (m_pair.m_threadProcessingMapping.TryGetValue(Thread.CurrentThread.ManagedThreadId, out currentThreadMode) &&
- currentThreadMode == m_processingMode)
+ if (m_pair.m_threadProcessingMode.Value == m_processingMode)
{
// If we're targeting the default scheduler and taskWasPreviouslyQueued is false,
// we know the default scheduler will allow it, so we can just execute it here.
@@ -729,25 +712,7 @@ namespace System.Threading.Tasks
internal static void ContractAssertMonitorStatus(object syncObj, bool held)
{
Debug.Assert(syncObj != null, "The monitor object to check must be provided.");
-#if PRENET45
-#if DEBUG
- // This check is expensive,
- // which is why it's protected by ShouldCheckMonitorStatus and controlled by an environment variable DEBUGSYNC.
- if (ShouldCheckMonitorStatus)
- {
- bool exceptionThrown;
- try
- {
- Monitor.Pulse(syncObj); // throws a SynchronizationLockException if the monitor isn't held by this thread
- exceptionThrown = false;
- }
- catch (SynchronizationLockException) { exceptionThrown = true; }
- Debug.Assert(held == !exceptionThrown, "The locking scheme was not correctly followed.");
- }
-#endif
-#else
Debug.Assert(Monitor.IsEntered(syncObj) == held, "The locking scheme was not correctly followed.");
-#endif
}
/// <summary>Gets the options to use for tasks.</summary>
@@ -759,12 +724,7 @@ namespace System.Threading.Tasks
/// <returns>The options to use.</returns>
internal static TaskCreationOptions GetCreationOptionsForTask(bool isReplacementReplica = false)
{
- TaskCreationOptions options =
-#if PRENET45
- TaskCreationOptions.None;
-#else
- TaskCreationOptions.DenyChildAttach;
-#endif
+ TaskCreationOptions options = TaskCreationOptions.DenyChildAttach;
if (isReplacementReplica) options |= TaskCreationOptions.PreferFairness;
return options;
}