diff options
author | Stephen Toub <stoub@microsoft.com> | 2018-05-08 01:18:44 -0400 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2018-05-07 22:18:44 -0700 |
commit | b511ceb8a712ee3d1340ea5093b1d33e19bae696 (patch) | |
tree | ac4e8bd0441fc164d120d6e47693688f172869b6 /src/mscorlib | |
parent | ba4225e5d918f2657fbbebf18be4c7323583a8cf (diff) | |
download | coreclr-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.cs | 80 |
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; } |