summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Threading/Tasks
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Threading/Tasks')
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs157
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs1
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs145
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs14
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/Parallel.cs3593
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs641
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs279
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs171
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs214
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/Task.cs716
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs17
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs54
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs17
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs259
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs1
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/future.cs171
16 files changed, 256 insertions, 6194 deletions
diff --git a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs b/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
deleted file mode 100644
index 71eb787..0000000
--- a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Security;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Threading.Tasks {
-
-/// <summary>
-/// Provides an adapter to make Begin/End pairs awaitable.
-/// In general, Task.Factory.FromAsync should be used for this purpose.
-/// However, for cases where absolute minimal overhead is required, this type
-/// may be used to making APM pairs awaitable while minimizing overhead.
-/// (APM = Asynchronous Programming Model or the Begin/End pattern.)
-/// </summary>
-/// <remarks>
-/// This instance may be reused repeatedly. However, it must only be used
-/// by a single APM invocation at a time. It's state will automatically be reset
-/// when the await completes.
-/// </remarks>
-/// <example>
-/// Usage sample:
-/// <code>
-/// static async Task CopyStreamAsync(Stream source, Stream dest) {
-///
-/// BeginEndAwaitableAdapter adapter = new BeginEndAwaitableAdapter();
-/// Byte[] buffer = new Byte[0x1000];
-///
-/// while (true) {
-///
-/// source.BeginRead(buffer, 0, buffer.Length, BeginEndAwaitableAdapter.Callback, adapter);
-/// Int32 numRead = source.EndRead(await adapter);
-/// if (numRead == 0)
-/// break;
-///
-/// dest.BeginWrite(buffer, 0, numRead, BeginEndAwaitableAdapter.Callback, adapter);
-/// dest.EndWrite(await adapter);
-/// }
-/// }
-/// </code>
-/// </example>
-internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion {
-
- /// <summary>A sentinel marker used to communicate between OnCompleted and the APM callback
- /// that the callback has already run, and thus OnCompleted needs to execute the callback.</summary>
- private readonly static Action CALLBACK_RAN = () => { };
-
- /// <summary>The IAsyncResult for the APM operation.</summary>
- private IAsyncResult _asyncResult;
-
- /// <summary>The continuation delegate provided to the awaiter.</summary>
- private Action _continuation;
-
-
- /// <summary>A callback to be passed as the AsyncCallback to an APM pair.
- /// It expects that an BeginEndAwaitableAdapter instance was supplied to the APM Begin method as the object state.</summary>
- public readonly static AsyncCallback Callback = (asyncResult) => {
-
- Debug.Assert(asyncResult != null);
- Debug.Assert(asyncResult.IsCompleted);
- Debug.Assert(asyncResult.AsyncState is BeginEndAwaitableAdapter);
-
- // Get the adapter object supplied as the "object state" to the Begin method
- BeginEndAwaitableAdapter adapter = (BeginEndAwaitableAdapter) asyncResult.AsyncState;
-
- // Store the IAsyncResult into it so that it's available to the awaiter
- adapter._asyncResult = asyncResult;
-
- // If the _continuation has already been set to the actual continuation by OnCompleted, then invoke the continuation.
- // Set _continuation to the CALLBACK_RAN sentinel so that IsCompleted returns true and OnCompleted sees the sentinel
- // and knows to invoke the callback.
- // Due to some known incorrect implementations of IAsyncResult in the Framework where CompletedSynchronously is lazily
- // set to true if it is first invoked after IsCompleted is true, we cannot rely here on CompletedSynchronously for
- // synchronization between the caller and the callback, and thus do not use CompletedSynchronously at all.
- Action continuation = Interlocked.Exchange(ref adapter._continuation, CALLBACK_RAN);
- if (continuation != null) {
-
- Debug.Assert(continuation != CALLBACK_RAN);
- continuation();
- }
- };
-
-
- /// <summary>Gets an awaiter.</summary>
- /// <returns>Returns itself as the awaiter.</returns>
- public BeginEndAwaitableAdapter GetAwaiter() {
-
- return this;
- }
-
-
- /// <summary>Gets whether the awaited APM operation completed.</summary>
- public bool IsCompleted {
- get {
-
- // We are completed if the callback was called and it set the continuation to the CALLBACK_RAN sentinel.
- // If the operation completes asynchronously, there's still a chance we'll see CALLBACK_RAN here, in which
- // case we're still good to keep running synchronously.
- return (_continuation == CALLBACK_RAN);
- }
- }
-
- /// <summary>Schedules the continuation to run when the operation completes.</summary>
- /// <param name="continuation">The continuation.</param>
- public void UnsafeOnCompleted(Action continuation) {
-
- Debug.Assert(continuation != null);
- OnCompleted(continuation);
- }
-
-
- /// <summary>Schedules the continuation to run when the operation completes.</summary>
- /// <param name="continuation">The continuation.</param>
- public void OnCompleted(Action continuation) {
-
- Debug.Assert(continuation != null);
-
- // If the continuation field is null, then set it to be the target continuation
- // so that when the operation completes, it'll invoke the continuation. If it's non-null,
- // it was already set to the CALLBACK_RAN-sentinel by the Callback, in which case we hit a very rare race condition
- // where the operation didn't complete synchronously but completed asynchronously between our
- // calls to IsCompleted and OnCompleted... in that case, just schedule a task to run the continuation.
- if (_continuation == CALLBACK_RAN
- || Interlocked.CompareExchange(ref _continuation, continuation, null) == CALLBACK_RAN) {
-
- Task.Run(continuation); // must run async at this point, or else we'd risk stack diving
- }
- }
-
-
- /// <summary>Gets the IAsyncResult for the APM operation after the operation completes, and then resets the adapter.</summary>
- /// <returns>The IAsyncResult for the operation.</returns>
- public IAsyncResult GetResult() {
-
- Debug.Assert(_asyncResult != null && _asyncResult.IsCompleted);
-
- // Get the IAsyncResult
- IAsyncResult result = _asyncResult;
-
- // Reset the adapter
- _asyncResult = null;
- _continuation = null;
-
- // Return the result
- return result;
- }
-
-} // class BeginEndAwaitableAdapter
-
-} // namespace
diff --git a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
index c7a96b0..a87406a 100644
--- a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
@@ -20,7 +20,6 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Security;
-using System.Security.Permissions;
namespace System.Threading.Tasks
{
diff --git a/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs b/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs
index c98e219..137afa1 100644
--- a/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs
@@ -12,7 +12,6 @@
using System;
using System.Security;
-using System.Security.Permissions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Diagnostics;
@@ -277,13 +276,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<TResult> function)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -306,13 +303,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, cancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -337,13 +332,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<TResult> function, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
- creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -379,13 +372,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task<TResult>.StartNew(
Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken,
- creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ creationOptions, InternalTaskOptions.None, scheduler);
}
/// <summary>
@@ -406,13 +397,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<Object, TResult> function, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -437,13 +426,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -470,13 +457,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
- creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -514,12 +499,10 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
- creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ creationOptions, InternalTaskOptions.None, scheduler);
}
//
@@ -604,11 +587,9 @@ namespace System.Threading.Tasks
/// <paramref name="endMethod"/> argument is null.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
/// asynchronous operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> FromAsync(IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
+ return FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler);
}
/// <summary>
@@ -630,14 +611,12 @@ namespace System.Threading.Tasks
/// value.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
/// asynchronous operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> FromAsync(
IAsyncResult asyncResult,
Func<IAsyncResult, TResult> endMethod,
TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark);
+ return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler);
}
@@ -665,27 +644,23 @@ namespace System.Threading.Tasks
/// value.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
/// asynchronous operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> FromAsync(
IAsyncResult asyncResult,
Func<IAsyncResult, TResult> endMethod,
TaskCreationOptions creationOptions,
TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark);
+ return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler);
}
- // internal overload that supports StackCrawlMark
- // We also need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
+ // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
// method can access the logic w/o declaring a TaskFactory<TResult> instance.
internal static Task<TResult> FromAsyncImpl(
IAsyncResult asyncResult,
Func<IAsyncResult, TResult> endFunction,
Action<IAsyncResult> endAction,
TaskCreationOptions creationOptions,
- TaskScheduler scheduler,
- ref StackCrawlMark stackMark)
+ TaskScheduler scheduler)
{
if (asyncResult == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult);
@@ -714,12 +689,12 @@ namespace System.Threading.Tasks
// Just specify this task as detached. No matter what happens, we want endMethod
// to be called -- even if the parent is canceled. So we don't want to flow
// RespectParentCancellation.
- Task t = new Task(delegate
+ Task t = new Task(new Action<object>(delegate
{
FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization:true);
- },
+ }),
(object)null, null,
- default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null, ref stackMark);
+ default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null);
if (AsyncCausalityTracer.LoggingOn)
AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Verbose, t.Id, "TaskFactory.FromAsync Callback", 0);
@@ -1428,14 +1403,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1459,14 +1432,12 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1496,14 +1467,12 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1543,15 +1512,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
/// <summary>
@@ -1571,14 +1538,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1603,15 +1568,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
CancellationToken cancellationToken)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1642,15 +1605,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1691,15 +1652,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
@@ -1707,7 +1666,7 @@ namespace System.Threading.Tasks
// Note: if you make any changes to this method, please do the same to the non-generic version too.
internal static Task<TResult> ContinueWhenAllImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
Func<Task<TAntecedentResult>[], TResult> continuationFunction, Action<Task<TAntecedentResult>[]> continuationAction,
- TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
@@ -1737,7 +1696,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
- continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationFunction, scheduler, cancellationToken, continuationOptions);
}
else
{
@@ -1746,7 +1705,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
- continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationAction, scheduler, cancellationToken, continuationOptions);
}
}
@@ -1754,7 +1713,7 @@ namespace System.Threading.Tasks
// Note: if you make any changes to this method, please do the same to the generic version too.
internal static Task<TResult> ContinueWhenAllImpl(Task[] tasks,
Func<Task[], TResult> continuationFunction, Action<Task[]> continuationAction,
- TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
@@ -1790,7 +1749,7 @@ namespace System.Threading.Tasks
completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
return ((Func<Task[], TResult>)state)(completedTasks.Result);
},
- continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationFunction, scheduler, cancellationToken, continuationOptions);
}
else
{
@@ -1804,7 +1763,7 @@ namespace System.Threading.Tasks
completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
((Action<Task[]>)state)(completedTasks.Result); return default(TResult);
},
- continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationAction, scheduler, cancellationToken, continuationOptions);
}
}
@@ -1828,14 +1787,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1859,14 +1816,12 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1896,14 +1851,12 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1943,15 +1896,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
/// <summary>
@@ -1971,14 +1922,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2003,15 +1952,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
CancellationToken cancellationToken)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2042,15 +1989,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2091,22 +2036,20 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
// Core implementation of ContinueWhenAny, non-generic version
// Note: if you make any changes to this method, be sure to do the same to the generic version
internal static Task<TResult> ContinueWhenAnyImpl(Task[] tasks,
Func<Task, TResult> continuationFunction, Action<Task> continuationAction,
- TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
@@ -2136,7 +2079,7 @@ namespace System.Threading.Tasks
//the following delegate avoids closure capture as much as possible
//completedTask.Result is the winning task; state == continuationAction
(completedTask, state) => { return ((Func<Task, TResult>)state)(completedTask.Result); },
- continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationFunction, scheduler, cancellationToken, continuationOptions);
}
else
{
@@ -2145,7 +2088,7 @@ namespace System.Threading.Tasks
//the following delegate avoids closure capture as much as possible
//completedTask.Result is the winning task; state == continuationAction
(completedTask, state) => { ((Action<Task>)state)(completedTask.Result); return default(TResult); },
- continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationAction, scheduler, cancellationToken, continuationOptions);
}
}
@@ -2154,7 +2097,7 @@ namespace System.Threading.Tasks
// Note: if you make any changes to this method, be sure to do the same to the non-generic version
internal static Task<TResult> ContinueWhenAnyImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
Func<Task<TAntecedentResult>, TResult> continuationFunction, Action<Task<TAntecedentResult>> continuationAction,
- TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler)
{
// check arguments
TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
@@ -2182,7 +2125,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// Use a cached delegate
GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
- continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationFunction, scheduler, cancellationToken, continuationOptions);
}
else
{
@@ -2190,7 +2133,7 @@ namespace System.Threading.Tasks
return starter.ContinueWith<TResult>(
// Use a cached delegate
GenericDelegateCache<TAntecedentResult,TResult>.CWAnyActionDelegate,
- continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ continuationAction, scheduler, cancellationToken, continuationOptions);
}
}
}
diff --git a/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs b/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
index b8155d0..32efd77 100644
--- a/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
@@ -19,16 +19,16 @@ namespace Windows.Foundation.Diagnostics
[Guid("50850B26-267E-451B-A890-AB6A370245EE")]
[WindowsRuntimeImport]
internal interface IAsyncCausalityTracerStatics
- {
- void TraceOperationCreation(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, string operationName, ulong relatedContext);
- void TraceOperationCompletion(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, AsyncCausalityStatus status);
- void TraceOperationRelation(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, CausalityRelation relation);
- void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, CausalitySynchronousWork work);
- void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySource source, CausalitySynchronousWork work);
+ {
+ void TraceOperationCreation(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, string operationName, ulong relatedContext);
+ void TraceOperationCompletion(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, AsyncCausalityStatus status);
+ void TraceOperationRelation(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, CausalityRelation relation);
+ void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, CausalitySynchronousWork work);
+ void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySource source, CausalitySynchronousWork work);
//These next 2 functions could've been represented as an event except that the EventRegistrationToken wasn't being propagated to WinRT
EventRegistrationToken add_TracingStatusChanged(System.EventHandler<TracingStatusChangedEventArgs> eventHandler);
void remove_TracingStatusChanged(EventRegistrationToken token);
- }
+ }
[ComImport]
[Guid("410B7711-FF3B-477F-9C9A-D2EFDA302DC3")]
diff --git a/src/mscorlib/src/System/Threading/Tasks/Parallel.cs b/src/mscorlib/src/System/Threading/Tasks/Parallel.cs
deleted file mode 100644
index 7808943..0000000
--- a/src/mscorlib/src/System/Threading/Tasks/Parallel.cs
+++ /dev/null
@@ -1,3593 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-//
-//
-// A helper class that contains parallel versions of various looping constructs. This
-// internally uses the task parallel library, but takes care to expose very little
-// evidence of this infrastructure being used.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-using System;
-using System.Diagnostics;
-using System.Collections;
-using System.Collections.Generic;
-using System.Collections.Concurrent;
-using System.Security.Permissions;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Diagnostics.Contracts;
-
-
-namespace System.Threading.Tasks
-{
- /// <summary>
- /// Stores options that configure the operation of methods on the
- /// <see cref="T:System.Threading.Tasks.Parallel">Parallel</see> class.
- /// </summary>
- /// <remarks>
- /// By default, methods on the Parallel class attempt to utilize all available processors, are non-cancelable, and target
- /// the default TaskScheduler (TaskScheduler.Default). <see cref="ParallelOptions"/> enables
- /// overriding these defaults.
- /// </remarks>
- public class ParallelOptions
- {
- private TaskScheduler m_scheduler;
- private int m_maxDegreeOfParallelism;
- private CancellationToken m_cancellationToken;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ParallelOptions"/> class.
- /// </summary>
- /// <remarks>
- /// This constructor initializes the instance with default values. <see cref="MaxDegreeOfParallelism"/>
- /// is initialized to -1, signifying that there is no upper bound set on how much parallelism should
- /// be employed. <see cref="CancellationToken"/> is initialized to a non-cancelable token,
- /// and <see cref="TaskScheduler"/> is initialized to the default scheduler (TaskScheduler.Default).
- /// All of these defaults may be overwritten using the property set accessors on the instance.
- /// </remarks>
- public ParallelOptions()
- {
- m_scheduler = TaskScheduler.Default;
- m_maxDegreeOfParallelism = -1;
- m_cancellationToken = CancellationToken.None;
- }
-
- /// <summary>
- /// Gets or sets the <see cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
- /// associated with this <see cref="ParallelOptions"/> instance. Setting this property to null
- /// indicates that the current scheduler should be used.
- /// </summary>
- public TaskScheduler TaskScheduler
- {
- get { return m_scheduler; }
- set { m_scheduler = value; }
- }
-
- // Convenience property used by TPL logic
- internal TaskScheduler EffectiveTaskScheduler
- {
- get
- {
- if (m_scheduler == null) return TaskScheduler.Current;
- else return m_scheduler;
- }
- }
-
- /// <summary>
- /// Gets or sets the maximum degree of parallelism enabled by this ParallelOptions instance.
- /// </summary>
- /// <remarks>
- /// The <see cref="MaxDegreeOfParallelism"/> limits the number of concurrent operations run by <see
- /// cref="T:System.Threading.Tasks.Parallel">Parallel</see> method calls that are passed this
- /// ParallelOptions instance to the set value, if it is positive. If <see
- /// cref="MaxDegreeOfParallelism"/> is -1, then there is no limit placed on the number of concurrently
- /// running operations.
- /// </remarks>
- /// <exception cref="T:System.ArgumentOutOfRangeException">
- /// The exception that is thrown when this <see cref="MaxDegreeOfParallelism"/> is set to 0 or some
- /// value less than -1.
- /// </exception>
- public int MaxDegreeOfParallelism
- {
- get { return m_maxDegreeOfParallelism; }
- set
- {
- if ((value == 0) || (value < -1))
- throw new ArgumentOutOfRangeException(nameof(MaxDegreeOfParallelism));
- m_maxDegreeOfParallelism = value;
- }
- }
-
- /// <summary>
- /// Gets or sets the <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
- /// associated with this <see cref="ParallelOptions"/> instance.
- /// </summary>
- /// <remarks>
- /// Providing a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
- /// to a <see cref="T:System.Threading.Tasks.Parallel">Parallel</see> method enables the operation to be
- /// exited early. Code external to the operation may cancel the token, and if the operation observes the
- /// token being set, it may exit early by throwing an
- /// <see cref="T:System.OperationCanceledException"/>.
- /// </remarks>
- public CancellationToken CancellationToken
- {
- get { return m_cancellationToken; }
- set { m_cancellationToken = value; }
- }
-
- internal int EffectiveMaxConcurrencyLevel
- {
- get
- {
- int rval = MaxDegreeOfParallelism;
- int schedulerMax = EffectiveTaskScheduler.MaximumConcurrencyLevel;
- if ((schedulerMax > 0) && (schedulerMax != Int32.MaxValue))
- {
- rval = (rval == -1) ? schedulerMax : Math.Min(schedulerMax, rval);
- }
- return rval;
- }
- }
- }
-
- /// <summary>
- /// Provides support for parallel loops and regions.
- /// </summary>
- /// <remarks>
- /// The <see cref="T:System.Threading.Tasks.Parallel"/> class provides library-based data parallel replacements
- /// for common operations such as for loops, for each loops, and execution of a set of statements.
- /// </remarks>
- public static class Parallel
- {
- // static counter for generating unique Fork/Join Context IDs to be used in ETW events
- internal static int s_forkJoinContextID;
-
- // We use a stride for loops to amortize the frequency of interlocked operations.
- internal const int DEFAULT_LOOP_STRIDE = 16;
-
- // Static variable to hold default parallel options
- internal static ParallelOptions s_defaultParallelOptions = new ParallelOptions();
-
- /// <summary>
- /// Executes each of the provided actions, possibly in parallel.
- /// </summary>
- /// <param name="actions">An array of <see cref="T:System.Action">Actions</see> to execute.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="actions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
- /// <paramref name="actions"/> array contains a null element.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown when any
- /// action in the <paramref name="actions"/> array throws an exception.</exception>
- /// <remarks>
- /// This method can be used to execute a set of operations, potentially in parallel.
- /// No guarantees are made about the order in which the operations execute or whether
- /// they execute in parallel. This method does not return until each of the
- /// provided operations has completed, regardless of whether completion
- /// occurs due to normal or exceptional termination.
- /// </remarks>
- public static void Invoke(params Action[] actions)
- {
- Invoke(s_defaultParallelOptions, actions);
- }
-
- /// <summary>
- /// Executes each of the provided actions, possibly in parallel.
- /// </summary>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="actions">An array of <see cref="T:System.Action">Actions</see> to execute.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="actions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
- /// <paramref name="actions"/> array contains a null element.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown when any
- /// action in the <paramref name="actions"/> array throws an exception.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <remarks>
- /// This method can be used to execute a set of operations, potentially in parallel.
- /// No guarantees are made about the order in which the operations execute or whether
- /// the they execute in parallel. This method does not return until each of the
- /// provided operations has completed, regardless of whether completion
- /// occurs due to normal or exceptional termination.
- /// </remarks>
- public static void Invoke(ParallelOptions parallelOptions, params Action[] actions)
- {
- if (actions == null)
- {
- throw new ArgumentNullException(nameof(actions));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- // Throw an ODE if we're passed a disposed CancellationToken.
- if (parallelOptions.CancellationToken.CanBeCanceled
- && AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
- {
- parallelOptions.CancellationToken.ThrowIfSourceDisposed();
- }
- // Quit early if we're already canceled -- avoid a bunch of work.
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- throw new OperationCanceledException(parallelOptions.CancellationToken);
-
- // We must validate that the actions array contains no null elements, and also
- // make a defensive copy of the actions array.
- Action[] actionsCopy = new Action[actions.Length];
- for (int i = 0; i < actionsCopy.Length; i++)
- {
- actionsCopy[i] = actions[i];
- if (actionsCopy[i] == null)
- {
- throw new ArgumentException(Environment.GetResourceString("Parallel_Invoke_ActionNull"));
- }
- }
-
- // ETW event for Parallel Invoke Begin
- int forkJoinContextID = 0;
- Task callerTask = null;
- if (TplEtwProvider.Log.IsEnabled())
- {
- forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
- callerTask = Task.InternalCurrent;
- TplEtwProvider.Log.ParallelInvokeBegin((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
- forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelInvoke,
- actionsCopy.Length);
- }
-
-#if DEBUG
- actions = null; // Ensure we don't accidentally use this below.
-#endif
-
- // If we have no work to do, we are done.
- if (actionsCopy.Length < 1) return;
-
- // In the algorithm below, if the number of actions is greater than this, we automatically
- // use Parallel.For() to handle the actions, rather than the Task-per-Action strategy.
- const int SMALL_ACTIONCOUNT_LIMIT = 10;
-
- try
- {
- // If we've gotten this far, it's time to process the actions.
- if ((actionsCopy.Length > SMALL_ACTIONCOUNT_LIMIT) ||
- (parallelOptions.MaxDegreeOfParallelism != -1 && parallelOptions.MaxDegreeOfParallelism < actionsCopy.Length))
- {
- // Used to hold any exceptions encountered during action processing
- ConcurrentQueue<Exception> exceptionQ = null; // will be lazily initialized if necessary
-
- // This is more efficient for a large number of actions, or for enforcing MaxDegreeOfParallelism.
- try
- {
- // Launch a self-replicating task to handle the execution of all actions.
- // The use of a self-replicating task allows us to use as many cores
- // as are available, and no more. The exception to this rule is
- // that, in the case of a blocked action, the ThreadPool may inject
- // extra threads, which means extra tasks can run.
- int actionIndex = 0;
- ParallelForReplicatingTask rootTask = new ParallelForReplicatingTask(parallelOptions, delegate
- {
- // Each for-task will pull an action at a time from the list
- int myIndex = Interlocked.Increment(ref actionIndex); // = index to use + 1
- while (myIndex <= actionsCopy.Length)
- {
- // Catch and store any exceptions. If we don't catch them, the self-replicating
- // task will exit, and that may cause other SR-tasks to exit.
- // And (absent cancellation) we want all actions to execute.
- try
- {
- actionsCopy[myIndex - 1]();
- }
- catch (Exception e)
- {
- LazyInitializer.EnsureInitialized<ConcurrentQueue<Exception>>(ref exceptionQ, () => { return new ConcurrentQueue<Exception>(); });
- exceptionQ.Enqueue(e);
- }
-
- // Check for cancellation. If it is encountered, then exit the delegate.
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- throw new OperationCanceledException(parallelOptions.CancellationToken);
-
- // You're still in the game. Grab your next action index.
- myIndex = Interlocked.Increment(ref actionIndex);
- }
- }, TaskCreationOptions.None, InternalTaskOptions.SelfReplicating);
-
- rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler);
- rootTask.Wait();
- }
- catch (Exception e)
- {
- LazyInitializer.EnsureInitialized<ConcurrentQueue<Exception>>(ref exceptionQ, () => { return new ConcurrentQueue<Exception>(); });
-
- // Since we're consuming all action exceptions, there are very few reasons that
- // we would see an exception here. Two that come to mind:
- // (1) An OCE thrown by one or more actions (AggregateException thrown)
- // (2) An exception thrown from the ParallelForReplicatingTask constructor
- // (regular exception thrown).
- // We'll need to cover them both.
- AggregateException ae = e as AggregateException;
- if (ae != null)
- {
- // Strip off outer container of an AggregateException, because downstream
- // logic needs OCEs to be at the top level.
- foreach (Exception exc in ae.InnerExceptions) exceptionQ.Enqueue(exc);
- }
- else
- {
- exceptionQ.Enqueue(e);
- }
- }
-
- // If we have encountered any exceptions, then throw.
- if ((exceptionQ != null) && (exceptionQ.Count > 0))
- {
- ThrowIfReducableToSingleOCE(exceptionQ, parallelOptions.CancellationToken);
- throw new AggregateException(exceptionQ);
- }
- }
- else
- {
- // This is more efficient for a small number of actions and no DOP support
-
- // Initialize our array of tasks, one per action.
- Task[] tasks = new Task[actionsCopy.Length];
-
- // One more check before we begin...
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- throw new OperationCanceledException(parallelOptions.CancellationToken);
-
- // Launch all actions as tasks
- for (int i = 1; i < tasks.Length; i++)
- {
- tasks[i] = Task.Factory.StartNew(actionsCopy[i], parallelOptions.CancellationToken, TaskCreationOptions.None,
- InternalTaskOptions.None, parallelOptions.EffectiveTaskScheduler);
- }
-
- // Optimization: Use current thread to run something before we block waiting for all tasks.
- tasks[0] = new Task(actionsCopy[0]);
- tasks[0].RunSynchronously(parallelOptions.EffectiveTaskScheduler);
-
- // Now wait for the tasks to complete. This will not unblock until all of
- // them complete, and it will throw an exception if one or more of them also
- // threw an exception. We let such exceptions go completely unhandled.
- try
- {
- if (tasks.Length <= 4)
- {
- // for 4 or less tasks, the sequential waitall version is faster
- Task.FastWaitAll(tasks);
- }
- else
- {
- // otherwise we revert to the regular WaitAll which delegates the multiple wait to the cooperative event.
- Task.WaitAll(tasks);
- }
- }
- catch (AggregateException aggExp)
- {
- // see if we can combine it into a single OCE. If not propagate the original exception
- ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
- throw;
- }
- finally
- {
- for (int i = 0; i < tasks.Length; i++)
- {
- if (tasks[i].IsCompleted) tasks[i].Dispose();
- }
- }
- }
- }
- finally
- {
- // ETW event for Parallel Invoke End
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelInvokeEnd((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
- forkJoinContextID);
- }
- }
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int32) as a parameter.
- /// </remarks>
- public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForWorker<object>(
- fromInclusive, toExclusive,
- s_defaultParallelOptions,
- body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int64) as a parameter.
- /// </remarks>
- public static ParallelLoopResult For(long fromInclusive, long toExclusive, Action<long> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForWorker64<object>(
- fromInclusive, toExclusive, s_defaultParallelOptions,
- body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int32) as a parameter.
- /// </remarks>
- public static ParallelLoopResult For(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Action<int> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForWorker<object>(
- fromInclusive, toExclusive, parallelOptions,
- body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int64) as a parameter.
- /// </remarks>
- public static ParallelLoopResult For(long fromInclusive, long toExclusive, ParallelOptions parallelOptions, Action<long> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForWorker64<object>(
- fromInclusive, toExclusive, parallelOptions,
- body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </para>
- /// <para>
- /// Calling <see cref="System.Threading.Tasks.ParallelLoopState.Break()">ParallelLoopState.Break()</see>
- /// informs the For operation that iterations after the current one need not
- /// execute. However, all iterations before the current one will still need to be executed if they have not already.
- /// Therefore, calling Break is similar to using a break operation within a
- /// conventional for loop in a language like C#, but it is not a perfect substitute: for example, there is no guarantee that iterations
- /// after the current one will definitely not execute.
- /// </para>
- /// <para>
- /// If executing all iterations before the current one is not necessary,
- /// <see cref="System.Threading.Tasks.ParallelLoopState.Stop()">ParallelLoopState.Stop()</see>
- /// should be preferred to using Break. Calling Stop informs the For loop that it may abandon all remaining
- /// iterations, regardless of whether they're for interations above or below the current,
- /// since all required work has already been completed. As with Break, however, there are no guarantees regarding
- /// which other iterations will not execute.
- /// </para>
- /// <para>
- /// When a loop is ended prematurely, the <see cref="T:ParallelLoopState"/> that's returned will contain
- /// relevant information about the loop's completion.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int, ParallelLoopState> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForWorker<object>(
- fromInclusive, toExclusive, s_defaultParallelOptions,
- null, body, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </remarks>
- public static ParallelLoopResult For(long fromInclusive, long toExclusive, Action<long, ParallelLoopState> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForWorker64<object>(
- fromInclusive, toExclusive, s_defaultParallelOptions,
- null, body, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </remarks>
- public static ParallelLoopResult For(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Action<int, ParallelLoopState> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForWorker<object>(
- fromInclusive, toExclusive, parallelOptions,
- null, body, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </remarks>
- public static ParallelLoopResult For(long fromInclusive, long toExclusive, ParallelOptions parallelOptions,
- Action<long, ParallelLoopState> body)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForWorker64<object>(
- fromInclusive, toExclusive, parallelOptions,
- null, body, null, null, null);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult For<TLocal>(
- int fromInclusive, int toExclusive,
- Func<TLocal> localInit,
- Func<int, ParallelLoopState, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
-
- return ForWorker(
- fromInclusive, toExclusive, s_defaultParallelOptions,
- null, null, body, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel. Supports 64-bit indices.
- /// </summary>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult For<TLocal>(
- long fromInclusive, long toExclusive,
- Func<TLocal> localInit,
- Func<long, ParallelLoopState, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
-
- return ForWorker64(
- fromInclusive, toExclusive, s_defaultParallelOptions,
- null, null, body, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult For<TLocal>(
- int fromInclusive, int toExclusive, ParallelOptions parallelOptions,
- Func<TLocal> localInit,
- Func<int, ParallelLoopState, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForWorker(
- fromInclusive, toExclusive, parallelOptions,
- null, null, body, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for loop in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="fromInclusive">The start index, inclusive.</param>
- /// <param name="toExclusive">The end index, exclusive.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
- /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult For<TLocal>(
- long fromInclusive, long toExclusive, ParallelOptions parallelOptions,
- Func<TLocal> localInit,
- Func<long, ParallelLoopState, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
-
- return ForWorker64(
- fromInclusive, toExclusive, parallelOptions,
- null, null, body, localInit, localFinally);
- }
-
-
-
-
-
-
-
- /// <summary>
- /// Performs the major work of the parallel for loop. It assumes that argument validation has already
- /// been performed by the caller. This function's whole purpose in life is to enable as much reuse of
- /// common implementation details for the various For overloads we offer. Without it, we'd end up
- /// with lots of duplicate code. It handles: (1) simple for loops, (2) for loops that depend on
- /// ParallelState, and (3) for loops with thread local data.
- ///
- /// </summary>
- /// <typeparam name="TLocal">The type of the local data.</typeparam>
- /// <param name="fromInclusive">The loop's start index, inclusive.</param>
- /// <param name="toExclusive">The loop's end index, exclusive.</param>
- /// <param name="parallelOptions">A ParallelOptions instance.</param>
- /// <param name="body">The simple loop body.</param>
- /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
- /// <param name="bodyWithLocal">The loop body for thread local state overloads.</param>
- /// <param name="localInit">A selector function that returns new thread local state.</param>
- /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
- /// <remarks>Only one of the body arguments may be supplied (i.e. they are exclusive).</remarks>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
- private static ParallelLoopResult ForWorker<TLocal>(
- int fromInclusive, int toExclusive,
- ParallelOptions parallelOptions,
- Action<int> body,
- Action<int, ParallelLoopState> bodyWithState,
- Func<int, ParallelLoopState, TLocal, TLocal> bodyWithLocal,
- Func<TLocal> localInit, Action<TLocal> localFinally)
- {
- Debug.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1,
- "expected exactly one body function to be supplied");
- Debug.Assert(bodyWithLocal != null || (localInit == null && localFinally == null),
- "thread local functions should only be supplied for loops w/ thread local bodies");
-
- // Instantiate our result. Specifics will be filled in later.
- ParallelLoopResult result = new ParallelLoopResult();
-
- // We just return immediately if 'to' is smaller (or equal to) 'from'.
- if (toExclusive <= fromInclusive)
- {
- result.m_completed = true;
- return result;
- }
-
- // For all loops we need a shared flag even though we don't have a body with state,
- // because the shared flag contains the exceptional bool, which triggers other workers
- // to exit their loops if one worker catches an exception
- ParallelLoopStateFlags32 sharedPStateFlags = new ParallelLoopStateFlags32();
-
- TaskCreationOptions creationOptions = TaskCreationOptions.None;
- InternalTaskOptions internalOptions = InternalTaskOptions.SelfReplicating;
-
- // Before getting started, do a quick peek to see if we have been canceled already
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- {
- throw new OperationCanceledException(parallelOptions.CancellationToken);
- }
-
- // initialize ranges with passed in loop arguments and expected number of workers
- int numExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ?
- PlatformHelper.ProcessorCount :
- parallelOptions.EffectiveMaxConcurrencyLevel;
- RangeManager rangeManager = new RangeManager(fromInclusive, toExclusive, 1, numExpectedWorkers);
-
- // Keep track of any cancellations
- OperationCanceledException oce = null;
-
- CancellationTokenRegistration ctr = new CancellationTokenRegistration();
-
- // if cancellation is enabled, we need to register a callback to stop the loop when it gets signaled
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr = parallelOptions.CancellationToken.InternalRegisterWithoutEC((o) =>
- {
- // Cause processing to stop
- sharedPStateFlags.Cancel();
- // Record our cancellation
- oce = new OperationCanceledException(parallelOptions.CancellationToken);
- }, null);
- }
-
- // ETW event for Parallel For begin
- int forkJoinContextID = 0;
- Task callingTask = null;
- if (TplEtwProvider.Log.IsEnabled())
- {
- forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
- callingTask = Task.InternalCurrent;
- TplEtwProvider.Log.ParallelLoopBegin((callingTask != null ? callingTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callingTask != null ? callingTask.Id : 0),
- forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelFor,
- fromInclusive, toExclusive);
- }
-
- ParallelForReplicatingTask rootTask = null;
-
- try
- {
- // this needs to be in try-block because it can throw in BuggyScheduler.MaxConcurrencyLevel
- rootTask = new ParallelForReplicatingTask(
- parallelOptions,
- delegate
- {
- //
- // first thing we do upon enterying the task is to register as a new "RangeWorker" with the
- // shared RangeManager instance.
- //
- // If this call returns a RangeWorker struct which wraps the state needed by this task
- //
- // We need to call FindNewWork32() on it to see whether there's a chunk available.
- //
-
-
- // Cache some information about the current task
- Task currentWorkerTask = Task.InternalCurrent;
- bool bIsRootTask = (currentWorkerTask == rootTask);
-
- RangeWorker currentWorker = new RangeWorker();
- Object savedStateFromPreviousReplica = currentWorkerTask.SavedStateFromPreviousReplica;
-
- if (savedStateFromPreviousReplica is RangeWorker)
- currentWorker = (RangeWorker)savedStateFromPreviousReplica;
- else
- currentWorker = rangeManager.RegisterNewWorker();
-
-
-
- // These are the local index values to be used in the sequential loop.
- // Their values filled in by FindNewWork32
- int nFromInclusiveLocal;
- int nToExclusiveLocal;
-
- if (currentWorker.FindNewWork32(out nFromInclusiveLocal, out nToExclusiveLocal) == false ||
- sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal) == true)
- {
- return; // no need to run
- }
-
- // ETW event for ParallelFor Worker Fork
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelFork((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
- forkJoinContextID);
- }
-
- TLocal localValue = default(TLocal);
- bool bLocalValueInitialized = false; // Tracks whether localInit ran without exceptions, so that we can skip localFinally if it wasn't
-
- try
- {
- // Create a new state object that references the shared "stopped" and "exceptional" flags
- // If needed, it will contain a new instance of thread-local state by invoking the selector.
- ParallelLoopState32 state = null;
-
- if (bodyWithState != null)
- {
- Debug.Assert(sharedPStateFlags != null);
- state = new ParallelLoopState32(sharedPStateFlags);
- }
- else if (bodyWithLocal != null)
- {
- Debug.Assert(sharedPStateFlags != null);
- state = new ParallelLoopState32(sharedPStateFlags);
- if (localInit != null)
- {
- localValue = localInit();
- bLocalValueInitialized = true;
- }
- }
-
- // initialize a loop timer which will help us decide whether we should exit early
- LoopTimer loopTimer = new LoopTimer(rootTask.ActiveChildCount);
-
- // Now perform the loop itself.
- do
- {
- if (body != null)
- {
- for (int j = nFromInclusiveLocal;
- j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
- || !sharedPStateFlags.ShouldExitLoop()); // the no-arg version is used since we have no state
- j += 1)
- {
-
- body(j);
- }
- }
- else if (bodyWithState != null)
- {
- for (int j = nFromInclusiveLocal;
- j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
- || !sharedPStateFlags.ShouldExitLoop(j));
- j += 1)
- {
-
- state.CurrentIteration = j;
- bodyWithState(j, state);
- }
- }
- else
- {
- for (int j = nFromInclusiveLocal;
- j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
- || !sharedPStateFlags.ShouldExitLoop(j));
- j += 1)
- {
- state.CurrentIteration = j;
- localValue = bodyWithLocal(j, state, localValue);
- }
- }
-
- // Cooperative multitasking workaround for AppDomain fairness.
- // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
- // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
- if (!bIsRootTask && loopTimer.LimitExceeded())
- {
- currentWorkerTask.SavedStateForNextReplica = (object)currentWorker;
- break;
- }
-
- }
- // Exit if we can't find new work, or if the loop was stoppped.
- while (currentWorker.FindNewWork32(out nFromInclusiveLocal, out nToExclusiveLocal) &&
- ((sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE) ||
- !sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal)));
- }
- catch
- {
- // if we catch an exception in a worker, we signal the other workers to exit the loop, and we rethrow
- sharedPStateFlags.SetExceptional();
- throw;
- }
- finally
- {
- // If a cleanup function was specified, call it. Otherwise, if the type is
- // IDisposable, we will invoke Dispose on behalf of the user.
- if (localFinally != null && bLocalValueInitialized)
- {
- localFinally(localValue);
- }
-
- // ETW event for ParallelFor Worker Join
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelJoin((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
- forkJoinContextID);
- }
- }
- },
- creationOptions, internalOptions);
-
- rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler); // might throw TSE
- rootTask.Wait();
-
- // If we made a cancellation registration, we need to clean it up now before observing the OCE
- // Otherwise we could be caught in the middle of a callback, and observe PLS_STOPPED, but oce = null
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
-
- // If we got through that with no exceptions, and we were canceled, then
- // throw our cancellation exception
- if (oce != null) throw oce;
- }
- catch (AggregateException aggExp)
- {
- // if we made a cancellation registration, and rootTask.Wait threw, we need to clean it up here
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
-
- // see if we can combine it into a single OCE. If not propagate the original exception
- ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
- throw;
- }
- catch (TaskSchedulerException)
- {
- // if we made a cancellation registration, and rootTask.RunSynchronously threw, we need to clean it up here
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
- throw;
- }
- finally
- {
- int sb_status = sharedPStateFlags.LoopStateFlags;
- result.m_completed = (sb_status == ParallelLoopStateFlags.PLS_NONE);
- if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
- {
- result.m_lowestBreakIteration = sharedPStateFlags.LowestBreakIteration;
- }
-
- if ((rootTask != null) && rootTask.IsCompleted) rootTask.Dispose();
-
- // ETW event for Parallel For End
- if (TplEtwProvider.Log.IsEnabled())
- {
- int nTotalIterations = 0;
-
- // calculate how many iterations we ran in total
- if (sb_status == ParallelLoopStateFlags.PLS_NONE)
- nTotalIterations = toExclusive - fromInclusive;
- else if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
- nTotalIterations = sharedPStateFlags.LowestBreakIteration - fromInclusive;
- else
- nTotalIterations = -1; //PLS_STOPPED! We can't determine this if we were stopped..
-
- TplEtwProvider.Log.ParallelLoopEnd((callingTask != null ? callingTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callingTask != null ? callingTask.Id : 0),
- forkJoinContextID, nTotalIterations);
- }
- }
-
- return result;
- }
-
- /// <summary>
- /// Performs the major work of the 64-bit parallel for loop. It assumes that argument validation has already
- /// been performed by the caller. This function's whole purpose in life is to enable as much reuse of
- /// common implementation details for the various For overloads we offer. Without it, we'd end up
- /// with lots of duplicate code. It handles: (1) simple for loops, (2) for loops that depend on
- /// ParallelState, and (3) for loops with thread local data.
- ///
- /// </summary>
- /// <typeparam name="TLocal">The type of the local data.</typeparam>
- /// <param name="fromInclusive">The loop's start index, inclusive.</param>
- /// <param name="toExclusive">The loop's end index, exclusive.</param>
- /// <param name="parallelOptions">A ParallelOptions instance.</param>
- /// <param name="body">The simple loop body.</param>
- /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
- /// <param name="bodyWithLocal">The loop body for thread local state overloads.</param>
- /// <param name="localInit">A selector function that returns new thread local state.</param>
- /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
- /// <remarks>Only one of the body arguments may be supplied (i.e. they are exclusive).</remarks>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
- private static ParallelLoopResult ForWorker64<TLocal>(
- long fromInclusive, long toExclusive,
- ParallelOptions parallelOptions,
- Action<long> body,
- Action<long, ParallelLoopState> bodyWithState,
- Func<long, ParallelLoopState, TLocal, TLocal> bodyWithLocal,
- Func<TLocal> localInit, Action<TLocal> localFinally)
- {
- Debug.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1,
- "expected exactly one body function to be supplied");
- Debug.Assert(bodyWithLocal != null || (localInit == null && localFinally == null),
- "thread local functions should only be supplied for loops w/ thread local bodies");
-
- // Instantiate our result. Specifics will be filled in later.
- ParallelLoopResult result = new ParallelLoopResult();
-
- // We just return immediately if 'to' is smaller (or equal to) 'from'.
- if (toExclusive <= fromInclusive)
- {
- result.m_completed = true;
- return result;
- }
-
- // For all loops we need a shared flag even though we don't have a body with state,
- // because the shared flag contains the exceptional bool, which triggers other workers
- // to exit their loops if one worker catches an exception
- ParallelLoopStateFlags64 sharedPStateFlags = new ParallelLoopStateFlags64();
-
- TaskCreationOptions creationOptions = TaskCreationOptions.None;
- InternalTaskOptions internalOptions = InternalTaskOptions.SelfReplicating;
-
- // Before getting started, do a quick peek to see if we have been canceled already
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- {
- throw new OperationCanceledException(parallelOptions.CancellationToken);
- }
-
- // initialize ranges with passed in loop arguments and expected number of workers
- int numExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ?
- PlatformHelper.ProcessorCount :
- parallelOptions.EffectiveMaxConcurrencyLevel;
- RangeManager rangeManager = new RangeManager(fromInclusive, toExclusive, 1, numExpectedWorkers);
-
- // Keep track of any cancellations
- OperationCanceledException oce = null;
-
- CancellationTokenRegistration ctr = new CancellationTokenRegistration();
-
- // if cancellation is enabled, we need to register a callback to stop the loop when it gets signaled
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr = parallelOptions.CancellationToken.InternalRegisterWithoutEC((o) =>
- {
- // Cause processing to stop
- sharedPStateFlags.Cancel();
- // Record our cancellation
- oce = new OperationCanceledException(parallelOptions.CancellationToken);
- }, null);
- }
-
- // ETW event for Parallel For begin
- Task callerTask = null;
- int forkJoinContextID = 0;
- if (TplEtwProvider.Log.IsEnabled())
- {
- forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
- callerTask = Task.InternalCurrent;
- TplEtwProvider.Log.ParallelLoopBegin((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
- forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelFor,
- fromInclusive, toExclusive);
- }
-
- ParallelForReplicatingTask rootTask = null;
-
- try
- {
- // this needs to be in try-block because it can throw in BuggyScheduler.MaxConcurrencyLevel
- rootTask = new ParallelForReplicatingTask(
- parallelOptions,
- delegate
- {
- //
- // first thing we do upon enterying the task is to register as a new "RangeWorker" with the
- // shared RangeManager instance.
- //
- // If this call returns a RangeWorker struct which wraps the state needed by this task
- //
- // We need to call FindNewWork() on it to see whether there's a chunk available.
- //
-
- // Cache some information about the current task
- Task currentWorkerTask = Task.InternalCurrent;
- bool bIsRootTask = (currentWorkerTask == rootTask);
-
- RangeWorker currentWorker = new RangeWorker();
- Object savedStateFromPreviousReplica = currentWorkerTask.SavedStateFromPreviousReplica;
-
- if (savedStateFromPreviousReplica is RangeWorker)
- currentWorker = (RangeWorker)savedStateFromPreviousReplica;
- else
- currentWorker = rangeManager.RegisterNewWorker();
-
-
- // These are the local index values to be used in the sequential loop.
- // Their values filled in by FindNewWork
- long nFromInclusiveLocal;
- long nToExclusiveLocal;
-
- if (currentWorker.FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal) == false ||
- sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal) == true)
- {
- return; // no need to run
- }
-
- // ETW event for ParallelFor Worker Fork
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelFork((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
- forkJoinContextID);
- }
-
- TLocal localValue = default(TLocal);
- bool bLocalValueInitialized = false; // Tracks whether localInit ran without exceptions, so that we can skip localFinally if it wasn't
-
- try
- {
-
- // Create a new state object that references the shared "stopped" and "exceptional" flags
- // If needed, it will contain a new instance of thread-local state by invoking the selector.
- ParallelLoopState64 state = null;
-
- if (bodyWithState != null)
- {
- Debug.Assert(sharedPStateFlags != null);
- state = new ParallelLoopState64(sharedPStateFlags);
- }
- else if (bodyWithLocal != null)
- {
- Debug.Assert(sharedPStateFlags != null);
- state = new ParallelLoopState64(sharedPStateFlags);
-
- // If a thread-local selector was supplied, invoke it. Otherwise, use the default.
- if (localInit != null)
- {
- localValue = localInit();
- bLocalValueInitialized = true;
- }
- }
-
- // initialize a loop timer which will help us decide whether we should exit early
- LoopTimer loopTimer = new LoopTimer(rootTask.ActiveChildCount);
-
- // Now perform the loop itself.
- do
- {
- if (body != null)
- {
- for (long j = nFromInclusiveLocal;
- j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
- || !sharedPStateFlags.ShouldExitLoop()); // the no-arg version is used since we have no state
- j += 1)
- {
- body(j);
- }
- }
- else if (bodyWithState != null)
- {
- for (long j = nFromInclusiveLocal;
- j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
- || !sharedPStateFlags.ShouldExitLoop(j));
- j += 1)
- {
- state.CurrentIteration = j;
- bodyWithState(j, state);
- }
- }
- else
- {
- for (long j = nFromInclusiveLocal;
- j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
- || !sharedPStateFlags.ShouldExitLoop(j));
- j += 1)
- {
- state.CurrentIteration = j;
- localValue = bodyWithLocal(j, state, localValue);
- }
- }
-
- // Cooperative multitasking workaround for AppDomain fairness.
- // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
- // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
- if (!bIsRootTask && loopTimer.LimitExceeded())
- {
- currentWorkerTask.SavedStateForNextReplica = (object)currentWorker;
- break;
- }
- }
- // Exit if we can't find new work, or if the loop was stoppped.
- while (currentWorker.FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal) &&
- ((sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE) ||
- !sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal)));
- }
- catch
- {
- // if we catch an exception in a worker, we signal the other workers to exit the loop, and we rethrow
- sharedPStateFlags.SetExceptional();
- throw;
- }
- finally
- {
- // If a cleanup function was specified, call it. Otherwise, if the type is
- // IDisposable, we will invoke Dispose on behalf of the user.
- if (localFinally != null && bLocalValueInitialized)
- {
- localFinally(localValue);
- }
-
- // ETW event for ParallelFor Worker Join
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelJoin((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
- forkJoinContextID);
- }
- }
- },
- creationOptions, internalOptions);
-
- rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler); // might throw TSE
- rootTask.Wait();
-
- // If we made a cancellation registration, we need to clean it up now before observing the OCE
- // Otherwise we could be caught in the middle of a callback, and observe PLS_STOPPED, but oce = null
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
-
- // If we got through that with no exceptions, and we were canceled, then
- // throw our cancellation exception
- if (oce != null) throw oce;
- }
- catch (AggregateException aggExp)
- {
- // if we made a cancellation registration, and rootTask.Wait threw, we need to clean it up here
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
-
- // see if we can combine it into a single OCE. If not propagate the original exception
- ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
- throw;
- }
- catch (TaskSchedulerException)
- {
- // if we made a cancellation registration, and rootTask.RunSynchronously threw, we need to clean it up here
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
- throw;
- }
- finally
- {
- int sb_status = sharedPStateFlags.LoopStateFlags;
- result.m_completed = (sb_status == ParallelLoopStateFlags.PLS_NONE);
- if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
- {
- result.m_lowestBreakIteration = sharedPStateFlags.LowestBreakIteration;
- }
-
- if ((rootTask != null) && rootTask.IsCompleted) rootTask.Dispose();
-
- // ETW event for Parallel For End
- if (TplEtwProvider.Log.IsEnabled())
- {
- long nTotalIterations = 0;
-
- // calculate how many iterations we ran in total
- if (sb_status == ParallelLoopStateFlags.PLS_NONE)
- nTotalIterations = toExclusive - fromInclusive;
- else if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
- nTotalIterations = sharedPStateFlags.LowestBreakIteration - fromInclusive;
- else
- nTotalIterations = -1; //PLS_STOPPED! We can't determine this if we were stopped..
-
- TplEtwProvider.Log.ParallelLoopEnd((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
- forkJoinContextID, nTotalIterations);
- }
- }
-
- return result;
- }
-
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the current element as a parameter.
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForEachWorker<TSource, object>(
- source, s_defaultParallelOptions, body, null, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the current element as a parameter.
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForEachWorker<TSource, object>(
- source, parallelOptions, body, null, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource, ParallelLoopState> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForEachWorker<TSource, object>(
- source, s_defaultParallelOptions, null, body, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource, ParallelLoopState> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForEachWorker<TSource, object>(
- source, parallelOptions, null, body, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and the current element's index (an Int64).
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource, ParallelLoopState, long> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return ForEachWorker<TSource, object>(
- source, s_defaultParallelOptions, null, null, body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and the current element's index (an Int64).
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource, ParallelLoopState, long> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForEachWorker<TSource, object>(
- source, parallelOptions, null, null, body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
-
- return ForEachWorker<TSource, TLocal>(
- source, s_defaultParallelOptions, null, null, null, body, null, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source,
- ParallelOptions parallelOptions, Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForEachWorker<TSource, TLocal>(
- source, parallelOptions, null, null, null, body, null, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
- /// state that may be shared amongst iterations that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> body, Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
-
- return ForEachWorker<TSource, TLocal>(
- source, s_defaultParallelOptions, null, null, null, null, body, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
- /// in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the data in the source.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// enumerable. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
- /// state that may be shared amongst iterations that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> body, Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return ForEachWorker<TSource, TLocal>(
- source, parallelOptions, null, null, null, null, body, localInit, localFinally);
- }
-
-
- /// <summary>
- /// Performs the major work of the parallel foreach loop. It assumes that argument validation has
- /// already been performed by the caller. This function's whole purpose in life is to enable as much
- /// reuse of common implementation details for the various For overloads we offer. Without it, we'd
- /// end up with lots of duplicate code. It handles: (1) simple foreach loops, (2) foreach loops that
- /// depend on ParallelState, and (3) foreach loops that access indices, (4) foreach loops with thread
- /// local data, and any necessary permutations thereof.
- ///
- /// </summary>
- /// <typeparam name="TSource">The type of the source data.</typeparam>
- /// <typeparam name="TLocal">The type of the local data.</typeparam>
- /// <param name="source">An enumerable data source.</param>
- /// <param name="parallelOptions">ParallelOptions instance to use with this ForEach-loop</param>
- /// <param name="body">The simple loop body.</param>
- /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
- /// <param name="bodyWithStateAndIndex">The loop body for ParallelState/indexed overloads.</param>
- /// <param name="bodyWithStateAndLocal">The loop body for ParallelState/thread local state overloads.</param>
- /// <param name="bodyWithEverything">The loop body for ParallelState/indexed/thread local state overloads.</param>
- /// <param name="localInit">A selector function that returns new thread local state.</param>
- /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
- /// <remarks>Only one of the bodyXX arguments may be supplied (i.e. they are exclusive).</remarks>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
- private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
- IEnumerable<TSource> source,
- ParallelOptions parallelOptions,
- Action<TSource> body,
- Action<TSource, ParallelLoopState> bodyWithState,
- Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
- Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
- Func<TLocal> localInit, Action<TLocal> localFinally)
- {
- Debug.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) +
- (bodyWithStateAndIndex == null ? 0 : 1) + (bodyWithStateAndLocal == null ? 0 : 1) + (bodyWithEverything == null ? 0 : 1)) == 1,
- "expected exactly one body function to be supplied");
- Debug.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null),
- "thread local functions should only be supplied for loops w/ thread local bodies");
-
- // Before getting started, do a quick peek to see if we have been canceled already
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- {
- throw new OperationCanceledException(parallelOptions.CancellationToken);
- }
-
- // If it's an array, we can use a fast-path that uses ldelems in the IL.
- TSource[] sourceAsArray = source as TSource[];
- if (sourceAsArray != null)
- {
- return ForEachWorker<TSource, TLocal>(
- sourceAsArray, parallelOptions, body, bodyWithState, bodyWithStateAndIndex, bodyWithStateAndLocal,
- bodyWithEverything, localInit, localFinally);
- }
-
- // If we can index into the list, we can use a faster code-path that doesn't result in
- // contention for the single, shared enumerator object.
- IList<TSource> sourceAsList = source as IList<TSource>;
- if (sourceAsList != null)
- {
- return ForEachWorker<TSource, TLocal>(
- sourceAsList, parallelOptions, body, bodyWithState, bodyWithStateAndIndex, bodyWithStateAndLocal,
- bodyWithEverything, localInit, localFinally);
- }
-
- // This is an honest-to-goodness IEnumerable. Wrap it in a Partitioner and defer to our
- // ForEach(Partitioner) logic.
- return PartitionerForEachWorker<TSource, TLocal>(Partitioner.Create(source), parallelOptions, body, bodyWithState,
- bodyWithStateAndIndex, bodyWithStateAndLocal, bodyWithEverything, localInit, localFinally);
-
- }
-
- /// <summary>
- /// A fast path for the more general ForEachWorker method above. This uses ldelem instructions to
- /// access the individual elements of the array, which will be faster.
- /// </summary>
- /// <typeparam name="TSource">The type of the source data.</typeparam>
- /// <typeparam name="TLocal">The type of the local data.</typeparam>
- /// <param name="array">An array data source.</param>
- /// <param name="parallelOptions">The options to use for execution.</param>
- /// <param name="body">The simple loop body.</param>
- /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
- /// <param name="bodyWithStateAndIndex">The loop body for indexed/ParallelLoopState overloads.</param>
- /// <param name="bodyWithStateAndLocal">The loop body for local/ParallelLoopState overloads.</param>
- /// <param name="bodyWithEverything">The loop body for the most generic overload.</param>
- /// <param name="localInit">A selector function that returns new thread local state.</param>
- /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
- private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
- TSource[] array,
- ParallelOptions parallelOptions,
- Action<TSource> body,
- Action<TSource, ParallelLoopState> bodyWithState,
- Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
- Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
- Func<TLocal> localInit, Action<TLocal> localFinally)
- {
- Debug.Assert(array != null);
- Debug.Assert(parallelOptions != null, "ForEachWorker(array): parallelOptions is null");
-
- int from = array.GetLowerBound(0);
- int to = array.GetUpperBound(0) + 1;
-
- if (body != null)
- {
- return ForWorker<object>(
- from, to, parallelOptions, (i) => body(array[i]), null, null, null, null);
- }
- else if (bodyWithState != null)
- {
- return ForWorker<object>(
- from, to, parallelOptions, null, (i, state) => bodyWithState(array[i], state), null, null, null);
- }
- else if (bodyWithStateAndIndex != null)
- {
- return ForWorker<object>(
- from, to, parallelOptions, null, (i, state) => bodyWithStateAndIndex(array[i], state, i), null, null, null);
- }
- else if (bodyWithStateAndLocal != null)
- {
- return ForWorker<TLocal>(
- from, to, parallelOptions, null, null, (i, state, local) => bodyWithStateAndLocal(array[i], state, local), localInit, localFinally);
- }
- else
- {
- return ForWorker<TLocal>(
- from, to, parallelOptions, null, null, (i, state, local) => bodyWithEverything(array[i], state, i, local), localInit, localFinally);
- }
- }
-
- /// <summary>
- /// A fast path for the more general ForEachWorker method above. This uses IList&lt;T&gt;'s indexer
- /// capabilities to access the individual elements of the list rather than an enumerator.
- /// </summary>
- /// <typeparam name="TSource">The type of the source data.</typeparam>
- /// <typeparam name="TLocal">The type of the local data.</typeparam>
- /// <param name="list">A list data source.</param>
- /// <param name="parallelOptions">The options to use for execution.</param>
- /// <param name="body">The simple loop body.</param>
- /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
- /// <param name="bodyWithStateAndIndex">The loop body for indexed/ParallelLoopState overloads.</param>
- /// <param name="bodyWithStateAndLocal">The loop body for local/ParallelLoopState overloads.</param>
- /// <param name="bodyWithEverything">The loop body for the most generic overload.</param>
- /// <param name="localInit">A selector function that returns new thread local state.</param>
- /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
- private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
- IList<TSource> list,
- ParallelOptions parallelOptions,
- Action<TSource> body,
- Action<TSource, ParallelLoopState> bodyWithState,
- Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
- Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
- Func<TLocal> localInit, Action<TLocal> localFinally)
- {
- Debug.Assert(list != null);
- Debug.Assert(parallelOptions != null, "ForEachWorker(list): parallelOptions is null");
-
- if (body != null)
- {
- return ForWorker<object>(
- 0, list.Count, parallelOptions, (i) => body(list[i]), null, null, null, null);
- }
- else if (bodyWithState != null)
- {
- return ForWorker<object>(
- 0, list.Count, parallelOptions, null, (i, state) => bodyWithState(list[i], state), null, null, null);
- }
- else if (bodyWithStateAndIndex != null)
- {
- return ForWorker<object>(
- 0, list.Count, parallelOptions, null, (i, state) => bodyWithStateAndIndex(list[i], state, i), null, null, null);
- }
- else if (bodyWithStateAndLocal != null)
- {
- return ForWorker<TLocal>(
- 0, list.Count, parallelOptions, null, null, (i, state, local) => bodyWithStateAndLocal(list[i], state, local), localInit, localFinally);
- }
- else
- {
- return ForWorker<TLocal>(
- 0, list.Count, parallelOptions, null, null, (i, state, local) => bodyWithEverything(list[i], state, i, local), localInit, localFinally);
- }
- }
-
-
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
- /// Partitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <param name="source">The Partitioner that contains the original data source.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> Partitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
- /// the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
- /// with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
- /// IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the current element as a parameter.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(
- Partitioner<TSource> source,
- Action<TSource> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return PartitionerForEachWorker<TSource, object>(source, s_defaultParallelOptions, body, null, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
- /// Partitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <param name="source">The Partitioner that contains the original data source.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> Partitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
- /// the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
- /// with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
- /// IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(
- Partitioner<TSource> source,
- Action<TSource, ParallelLoopState> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- return PartitionerForEachWorker<TSource, object>(source, s_defaultParallelOptions, null, body, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
- /// OrderablePartitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner do not return the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IList with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and the current element's index (an Int64).
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(
- OrderablePartitioner<TSource> source,
- Action<TSource, ParallelLoopState, long> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
-
- if (!source.KeysNormalized)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
- }
-
- return PartitionerForEachWorker<TSource, object>(source, s_defaultParallelOptions, null, null, body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
- /// Partitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">The Partitioner that contains the original data source.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> Partitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
- /// the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
- /// with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
- /// IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(
- Partitioner<TSource> source,
- Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
-
- return PartitionerForEachWorker<TSource, TLocal>(source, s_defaultParallelOptions, null, null, null, body, null, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
- /// OrderablePartitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner do not return the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IList with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
- /// state that may be shared amongst iterations that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(
- OrderablePartitioner<TSource> source,
- Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
-
- if (!source.KeysNormalized)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
- }
-
- return PartitionerForEachWorker<TSource, TLocal>(source, s_defaultParallelOptions, null, null, null, null, body, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
- /// Partitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <param name="source">The Partitioner that contains the original data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> Partitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
- /// the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
- /// with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
- /// IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the current element as a parameter.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(
- Partitioner<TSource> source,
- ParallelOptions parallelOptions,
- Action<TSource> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return PartitionerForEachWorker<TSource, object>(source, parallelOptions, body, null, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
- /// Partitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <param name="source">The Partitioner that contains the original data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> Partitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
- /// the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
- /// with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
- /// IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(
- Partitioner<TSource> source,
- ParallelOptions parallelOptions,
- Action<TSource, ParallelLoopState> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return PartitionerForEachWorker<TSource, object>(source, parallelOptions, null, body, null, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
- /// OrderablePartitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner do not return the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IList with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and the current element's index (an Int64).
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource>(
- OrderablePartitioner<TSource> source,
- ParallelOptions parallelOptions,
- Action<TSource, ParallelLoopState, long> body)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- if (!source.KeysNormalized)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
- }
-
- return PartitionerForEachWorker<TSource, object>(source, parallelOptions, null, null, body, null, null, null, null);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
- /// Partitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">The Partitioner that contains the original data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> Partitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
- /// the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
- /// with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
- /// IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
- /// that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(
- Partitioner<TSource> source,
- ParallelOptions parallelOptions,
- Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- return PartitionerForEachWorker<TSource, TLocal>(source, parallelOptions, null, null, null, body, null, localInit, localFinally);
- }
-
- /// <summary>
- /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
- /// OrderablePartitioner</see> in which iterations may run in parallel.
- /// </summary>
- /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
- /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
- /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
- /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
- /// instance that configures the behavior of this operation.</param>
- /// <param name="localInit">The function delegate that returns the initial state of the local data
- /// for each thread.</param>
- /// <param name="body">The delegate that is invoked once per iteration.</param>
- /// <param name="localFinally">The delegate that performs a final action on the local state of each
- /// thread.</param>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="parallelOptions"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
- /// argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localInit"/> argument is null.</exception>
- /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
- /// <paramref name="localFinally"/> argument is null.</exception>
- /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
- /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
- /// argument is set</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
- /// false.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
- /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner do not return the correct number of partitions.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IList with at least one null value.</exception>
- /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
- /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
- /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
- /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
- /// thrown from one of the specified delegates.</exception>
- /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
- /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
- /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
- /// <paramref name="parallelOptions"/> has been disposed.</exception>
- /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
- /// that contains information on what portion of the loop completed.</returns>
- /// <remarks>
- /// <para>
- /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
- /// the elements to be processed, in place of the original data source. If the current element's
- /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
- /// OrderablePartitioner</see>.
- /// </para>
- /// <para>
- /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
- /// Partitioner. It is provided with the following parameters: the current element,
- /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
- /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
- /// state that may be shared amongst iterations that execute on the same thread.
- /// </para>
- /// <para>
- /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
- /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
- /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
- /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
- /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
- /// action on each thread's local state.
- /// </para>
- /// </remarks>
- public static ParallelLoopResult ForEach<TSource, TLocal>(
- OrderablePartitioner<TSource> source,
- ParallelOptions parallelOptions,
- Func<TLocal> localInit,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> body,
- Action<TLocal> localFinally)
- {
- if (source == null)
- {
- throw new ArgumentNullException(nameof(source));
- }
- if (body == null)
- {
- throw new ArgumentNullException(nameof(body));
- }
- if (localInit == null)
- {
- throw new ArgumentNullException(nameof(localInit));
- }
- if (localFinally == null)
- {
- throw new ArgumentNullException(nameof(localFinally));
- }
- if (parallelOptions == null)
- {
- throw new ArgumentNullException(nameof(parallelOptions));
- }
-
- if (!source.KeysNormalized)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
- }
-
- return PartitionerForEachWorker<TSource, TLocal>(source, parallelOptions, null, null, null, null, body, localInit, localFinally);
- }
-
- // Main worker method for Parallel.ForEach() calls w/ Partitioners.
- private static ParallelLoopResult PartitionerForEachWorker<TSource, TLocal>(
- Partitioner<TSource> source, // Might be OrderablePartitioner
- ParallelOptions parallelOptions,
- Action<TSource> simpleBody,
- Action<TSource, ParallelLoopState> bodyWithState,
- Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
- Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
- Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
- Func<TLocal> localInit,
- Action<TLocal> localFinally)
- {
- Debug.Assert(((simpleBody == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) +
- (bodyWithStateAndIndex == null ? 0 : 1) + (bodyWithStateAndLocal == null ? 0 : 1) + (bodyWithEverything == null ? 0 : 1)) == 1,
- "PartitionForEach: expected exactly one body function to be supplied");
- Debug.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null),
- "PartitionForEach: thread local functions should only be supplied for loops w/ thread local bodies");
-
- OrderablePartitioner<TSource> orderedSource = source as OrderablePartitioner<TSource>;
- Debug.Assert((orderedSource != null) || (bodyWithStateAndIndex == null && bodyWithEverything == null),
- "PartitionForEach: bodies with indices are only allowable for OrderablePartitioner");
-
- if (!source.SupportsDynamicPartitions)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_PartitionerNotDynamic"));
- }
-
- // Before getting started, do a quick peek to see if we have been canceled already
- if (parallelOptions.CancellationToken.IsCancellationRequested)
- {
- throw new OperationCanceledException(parallelOptions.CancellationToken);
- }
-
- // ETW event for Parallel For begin
- int forkJoinContextID = 0;
- Task callerTask = null;
- if (TplEtwProvider.Log.IsEnabled())
- {
- forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
- callerTask = Task.InternalCurrent;
- TplEtwProvider.Log.ParallelLoopBegin((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
- forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelForEach,
- 0, 0);
- }
-
- // For all loops we need a shared flag even though we don't have a body with state,
- // because the shared flag contains the exceptional bool, which triggers other workers
- // to exit their loops if one worker catches an exception
- ParallelLoopStateFlags64 sharedPStateFlags = new ParallelLoopStateFlags64();
-
- // Instantiate our result. Specifics will be filled in later.
- ParallelLoopResult result = new ParallelLoopResult();
-
- // Keep track of any cancellations
- OperationCanceledException oce = null;
-
- CancellationTokenRegistration ctr = new CancellationTokenRegistration();
-
- // if cancellation is enabled, we need to register a callback to stop the loop when it gets signaled
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr = parallelOptions.CancellationToken.InternalRegisterWithoutEC((o) =>
- {
- // Cause processing to stop
- sharedPStateFlags.Cancel();
- // Record our cancellation
- oce = new OperationCanceledException(parallelOptions.CancellationToken);
- }, null);
- }
-
- // Get our dynamic partitioner -- depends on whether source is castable to OrderablePartitioner
- // Also, do some error checking.
- IEnumerable<TSource> partitionerSource = null;
- IEnumerable<KeyValuePair<long, TSource>> orderablePartitionerSource = null;
- if (orderedSource != null)
- {
- orderablePartitionerSource = orderedSource.GetOrderableDynamicPartitions();
- if (orderablePartitionerSource == null)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_PartitionerReturnedNull"));
- }
- }
- else
- {
- partitionerSource = source.GetDynamicPartitions();
- if (partitionerSource == null)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_PartitionerReturnedNull"));
- }
- }
-
- ParallelForReplicatingTask rootTask = null;
-
- // This is the action that will be run by each replicable task.
- Action partitionAction = delegate
- {
- Task currentWorkerTask = Task.InternalCurrent;
-
- // ETW event for ParallelForEach Worker Fork
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelFork((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
- forkJoinContextID);
- }
-
- TLocal localValue = default(TLocal);
- bool bLocalValueInitialized = false; // Tracks whether localInit ran without exceptions, so that we can skip localFinally if it wasn't
- IDisposable myPartitionToDispose = null;
-
- try
- {
- // Create a new state object that references the shared "stopped" and "exceptional" flags.
- // If needed, it will contain a new instance of thread-local state by invoking the selector.
- ParallelLoopState64 state = null;
-
- if (bodyWithState != null || bodyWithStateAndIndex != null)
- {
- state = new ParallelLoopState64(sharedPStateFlags);
- }
- else if (bodyWithStateAndLocal != null || bodyWithEverything != null)
- {
- state = new ParallelLoopState64(sharedPStateFlags);
- // If a thread-local selector was supplied, invoke it. Otherwise, stick with the default.
- if (localInit != null)
- {
- localValue = localInit();
- bLocalValueInitialized = true;
- }
- }
-
-
- bool bIsRootTask = (rootTask == currentWorkerTask);
-
- // initialize a loop timer which will help us decide whether we should exit early
- LoopTimer loopTimer = new LoopTimer(rootTask.ActiveChildCount);
-
- if (orderedSource != null)
- {
- // Use this path for OrderablePartitioner
-
-
- // first check if there's saved state from a previous replica that we might be replacing.
- // the only state to be passed down in such a transition is the enumerator
- IEnumerator<KeyValuePair<long, TSource>> myPartition = currentWorkerTask.SavedStateFromPreviousReplica as IEnumerator<KeyValuePair<long, TSource>>;
- if (myPartition == null)
- {
- // apparently we're a brand new replica, get a fresh enumerator from the partitioner
- myPartition = orderablePartitionerSource.GetEnumerator();
- if (myPartition == null)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_NullEnumerator"));
- }
- }
- myPartitionToDispose = myPartition;
-
- while (myPartition.MoveNext())
- {
- KeyValuePair<long, TSource> kvp = myPartition.Current;
- long index = kvp.Key;
- TSource value = kvp.Value;
-
- // Update our iteration index
- if (state != null) state.CurrentIteration = index;
-
- if (simpleBody != null)
- simpleBody(value);
- else if (bodyWithState != null)
- bodyWithState(value, state);
- else if (bodyWithStateAndIndex != null)
- bodyWithStateAndIndex(value, state, index);
- else if (bodyWithStateAndLocal != null)
- localValue = bodyWithStateAndLocal(value, state, localValue);
- else
- localValue = bodyWithEverything(value, state, index, localValue);
-
- if (sharedPStateFlags.ShouldExitLoop(index)) break;
-
- // Cooperative multitasking workaround for AppDomain fairness.
- // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
- // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
- if (!bIsRootTask && loopTimer.LimitExceeded())
- {
- currentWorkerTask.SavedStateForNextReplica = myPartition;
- myPartitionToDispose = null;
- break;
- }
- }
-
- }
- else
- {
- // Use this path for Partitioner that is not OrderablePartitioner
-
- // first check if there's saved state from a previous replica that we might be replacing.
- // the only state to be passed down in such a transition is the enumerator
- IEnumerator<TSource> myPartition = currentWorkerTask.SavedStateFromPreviousReplica as IEnumerator<TSource>;
- if (myPartition == null)
- {
- // apparently we're a brand new replica, get a fresh enumerator from the partitioner
- myPartition = partitionerSource.GetEnumerator();
- if (myPartition == null)
- {
- throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_NullEnumerator"));
- }
- }
- myPartitionToDispose = myPartition;
-
- // I'm not going to try to maintain this
- if (state != null)
- state.CurrentIteration = 0;
-
- while (myPartition.MoveNext())
- {
- TSource t = myPartition.Current;
-
- if (simpleBody != null)
- simpleBody(t);
- else if (bodyWithState != null)
- bodyWithState(t, state);
- else if (bodyWithStateAndLocal != null)
- localValue = bodyWithStateAndLocal(t, state, localValue);
- else
- Debug.Assert(false, "PartitionerForEach: illegal body type in Partitioner handler");
-
-
- // Any break, stop or exception causes us to halt
- // We don't have the global indexing information to discriminate whether or not
- // we are before or after a break point.
- if (sharedPStateFlags.LoopStateFlags != ParallelLoopStateFlags.PLS_NONE)
- break;
-
- // Cooperative multitasking workaround for AppDomain fairness.
- // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
- // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
- if (!bIsRootTask && loopTimer.LimitExceeded())
- {
- currentWorkerTask.SavedStateForNextReplica = myPartition;
- myPartitionToDispose = null;
- break;
- }
- }
- }
- }
- catch
- {
- // Inform other tasks of the exception, then rethrow
- sharedPStateFlags.SetExceptional();
- throw;
- }
- finally
- {
- if (localFinally != null && bLocalValueInitialized)
- {
- localFinally(localValue);
- }
-
- if (myPartitionToDispose != null)
- {
- myPartitionToDispose.Dispose();
- }
-
- // ETW event for ParallelFor Worker Join
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelJoin((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
- forkJoinContextID);
- }
- }
- };
-
- try
- {
- // Create and start the self-replicating task.
- // This needs to be in try-block because it can throw in BuggyScheduler.MaxConcurrencyLevel
- rootTask = new ParallelForReplicatingTask(parallelOptions, partitionAction, TaskCreationOptions.None,
- InternalTaskOptions.SelfReplicating);
-
- // And process it's completion...
- // Moved inside try{} block because faulty scheduler may throw here.
- rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler);
-
- rootTask.Wait();
-
- // If we made a cancellation registration, we need to clean it up now before observing the OCE
- // Otherwise we could be caught in the middle of a callback, and observe PLS_STOPPED, but oce = null
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
-
- // If we got through that with no exceptions, and we were canceled, then
- // throw our cancellation exception
- if (oce != null) throw oce;
- }
- catch (AggregateException aggExp)
- {
- // if we made a cancellation registration, and rootTask.Wait threw, we need to clean it up here
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
-
- // see if we can combine it into a single OCE. If not propagate the original exception
- ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
- throw;
- }
- catch (TaskSchedulerException)
- {
- // if we made a cancellation registration, and either we threw an exception constructing rootTask or
- // rootTask.RunSynchronously threw, we need to clean it up here.
- if (parallelOptions.CancellationToken.CanBeCanceled)
- {
- ctr.Dispose();
- }
- throw;
- }
- finally
- {
- int sb_status = sharedPStateFlags.LoopStateFlags;
- result.m_completed = (sb_status == ParallelLoopStateFlags.PLS_NONE);
- if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
- {
- result.m_lowestBreakIteration = sharedPStateFlags.LowestBreakIteration;
- }
-
- if ((rootTask != null) && rootTask.IsCompleted) rootTask.Dispose();
-
- //dispose the partitioner source if it implements IDisposable
- IDisposable d = null;
- if (orderablePartitionerSource != null)
- {
- d = orderablePartitionerSource as IDisposable;
- }
- else
- {
- d = partitionerSource as IDisposable;
- }
-
- if (d != null)
- {
- d.Dispose();
- }
-
- // ETW event for Parallel For End
- if (TplEtwProvider.Log.IsEnabled())
- {
- TplEtwProvider.Log.ParallelLoopEnd((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
- forkJoinContextID, 0);
- }
- }
-
- return result;
- }
-
- /// <summary>
- /// Internal utility function that implements the OCE filtering behavior for all Parallel.* APIs.
- /// Throws a single OperationCancelledException object with the token if the Exception collection only contains
- /// OperationCancelledExceptions with the given CancellationToken.
- ///
- /// </summary>
- /// <param name="excCollection"> The exception collection to filter</param>
- /// <param name="ct"> The CancellationToken expected on all inner exceptions</param>
- /// <returns></returns>
- internal static void ThrowIfReducableToSingleOCE(IEnumerable<Exception> excCollection, CancellationToken ct)
- {
- bool bCollectionNotZeroLength = false;
- if (ct.IsCancellationRequested)
- {
- foreach (Exception e in excCollection)
- {
- bCollectionNotZeroLength = true;
- OperationCanceledException oce = e as OperationCanceledException;
- if (oce == null || oce.CancellationToken != ct)
- {
- // mismatch found
- return;
- }
- }
-
- // all exceptions are OCEs with this token, let's throw it
- if (bCollectionNotZeroLength) throw new OperationCanceledException(ct);
- }
- }
-
- internal struct LoopTimer
- {
- public LoopTimer(int nWorkerTaskIndex)
- {
- // This logic ensures that we have a diversity of timeouts across worker tasks (100, 150, 200, 250, 100, etc)
- // Otherwise all worker will try to timeout at precisely the same point, which is bad if the work is just about to finish
- int timeOut = s_BaseNotifyPeriodMS + (nWorkerTaskIndex % PlatformHelper.ProcessorCount) * s_NotifyPeriodIncrementMS;
-
- m_timeLimit = Environment.TickCount + timeOut;
- }
-
- public bool LimitExceeded()
- {
- Debug.Assert(m_timeLimit != 0, "Probably the default initializer for LoopTimer was used somewhere");
-
- // comparing against the next expected time saves an addition operation here
- // Also we omit the comparison for wrap around here. The only side effect is one extra early yield every 38 days.
- return (Environment.TickCount > m_timeLimit);
- }
-
- const int s_BaseNotifyPeriodMS = 100;
- const int s_NotifyPeriodIncrementMS = 50;
-
- private int m_timeLimit;
- }
-
- }
-
-}
diff --git a/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs b/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs
deleted file mode 100644
index 6a62cf8..0000000
--- a/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs
+++ /dev/null
@@ -1,641 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-// ParallelState.cs
-//
-//
-// A non-generic and generic parallel state class, used by the Parallel helper class
-// for parallel loop management.
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-using System.Diagnostics;
-using System.Security.Permissions;
-using System.Diagnostics.Contracts;
-
-// Prevents compiler warnings/errors regarding the use of ref params in Interlocked methods
-#pragma warning disable 0420
-
-namespace System.Threading.Tasks
-{
-
- /// <summary>
- /// Enables iterations of <see cref="T:System.Threading.Tasks.Parallel"/> loops to interact with
- /// other iterations.
- /// </summary>
- [DebuggerDisplay("ShouldExitCurrentIteration = {ShouldExitCurrentIteration}")]
- public class ParallelLoopState
- {
- // Derived classes will track a ParallelStateFlags32 or ParallelStateFlags64.
- // So this is slightly redundant, but it enables us to implement some
- // methods in this base class.
- private ParallelLoopStateFlags m_flagsBase;
-
- internal ParallelLoopState(ParallelLoopStateFlags fbase)
- {
- m_flagsBase = fbase;
- }
-
- /// <summary>
- /// Internal/virtual support for ShouldExitCurrentIteration.
- /// </summary>
- internal virtual bool InternalShouldExitCurrentIteration
- {
- get
- {
- Debug.Assert(false);
- throw new NotSupportedException(
- Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod"));
- }
- }
-
- /// <summary>
- /// Gets whether the current iteration of the loop should exit based
- /// on requests made by this or other iterations.
- /// </summary>
- /// <remarks>
- /// When an iteration of a loop calls <see cref="Break()"/> or <see cref="Stop()"/>, or
- /// when one throws an exception, or when the loop is canceled, the <see cref="Parallel"/> class will proactively
- /// attempt to prohibit additional iterations of the loop from starting execution.
- /// However, there may be cases where it is unable to prevent additional iterations from starting.
- /// It may also be the case that a long-running iteration has already begun execution. In such
- /// cases, iterations may explicitly check the <see cref="ShouldExitCurrentIteration"/> property and
- /// cease execution if the property returns true.
- /// </remarks>
- public bool ShouldExitCurrentIteration
- {
- get
- {
- return InternalShouldExitCurrentIteration;
- }
- }
-
- /// <summary>
- /// Gets whether any iteration of the loop has called <see cref="Stop()"/>.
- /// </summary>
- public bool IsStopped
- {
- get
- {
- return ((m_flagsBase.LoopStateFlags & ParallelLoopStateFlags.PLS_STOPPED) != 0);
- }
- }
-
- /// <summary>
- /// Gets whether any iteration of the loop has thrown an exception that went unhandled by that
- /// iteration.
- /// </summary>
- public bool IsExceptional
- {
- get
- {
- return ((m_flagsBase.LoopStateFlags & ParallelLoopStateFlags.PLS_EXCEPTIONAL) != 0);
- }
- }
-
- /// <summary>
- /// Internal/virtual support for LowestBreakIteration.
- /// </summary>
- internal virtual long? InternalLowestBreakIteration
- {
- get
- {
- Debug.Assert(false);
- throw new NotSupportedException(
- Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod"));
- }
- }
-
- /// <summary>
- /// Gets the lowest iteration of the loop from which <see cref="Break()"/> was called.
- /// </summary>
- /// <remarks>
- /// If no iteration of the loop called <see cref="Break()"/>, this property will return null.
- /// </remarks>
- public long? LowestBreakIteration
- {
- get
- {
- return InternalLowestBreakIteration;
- }
- }
-
- /// <summary>
- /// Communicates that the <see cref="Parallel"/> loop should cease execution at the system's earliest
- /// convenience.
- /// </summary>
- /// <exception cref="T:System.InvalidOperationException">
- /// The <see cref="Break()"/> method was previously called. <see cref="Break()"/> and <see
- /// cref="Stop()"/> may not be used in combination by iterations of the same loop.
- /// </exception>
- /// <remarks>
- /// <para>
- /// <see cref="Stop()"/> may be used to communicate to the loop that no other iterations need be run.
- /// For long-running iterations that may already be executing, <see cref="Stop()"/> causes <see cref="IsStopped"/>
- /// to return true for all other iterations of the loop, such that another iteration may check <see
- /// cref="IsStopped"/> and exit early if it's observed to be true.
- /// </para>
- /// <para>
- /// <see cref="Stop()"/> is typically employed in search-based algorithms, where once a result is found,
- /// no other iterations need be executed.
- /// </para>
- /// </remarks>
- public void Stop()
- {
- m_flagsBase.Stop();
- }
-
- // Internal/virtual support for Break().
- internal virtual void InternalBreak()
- {
- Debug.Assert(false);
- throw new NotSupportedException(
- Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod"));
- }
-
- /// <summary>
- /// Communicates that the <see cref="Parallel"/> loop should cease execution at the system's earliest
- /// convenience of iterations beyond the current iteration.
- /// </summary>
- /// <exception cref="T:System.InvalidOperationException">
- /// The <see cref="Stop()"/> method was previously called. <see cref="Break()"/> and <see cref="Stop()"/>
- /// may not be used in combination by iterations of the same loop.
- /// </exception>
- /// <remarks>
- /// <para>
- /// <see cref="Break()"/> may be used to communicate to the loop that no other iterations after the
- /// current iteration need be run. For example, if <see cref="Break()"/> is called from the 100th
- /// iteration of a for loop iterating in parallel from 0 to 1000, all iterations less than 100 should
- /// still be run, but the iterations from 101 through to 1000 are not necessary.
- /// </para>
- /// <para>
- /// For long-running iterations that may already be executing, <see cref="Break()"/> causes <see
- /// cref="LowestBreakIteration"/>
- /// to be set to the current iteration's index if the current index is less than the current value of
- /// <see cref="LowestBreakIteration"/>.
- /// </para>
- /// <para>
- /// <see cref="Break()"/> is typically employed in search-based algorithms where an ordering is
- /// present in the data source.
- /// </para>
- /// </remarks>
- public void Break()
- {
- InternalBreak();
- }
-
- // Helper method to avoid repeating Break() logic between ParallelState32 and ParallelState32<TLocal>
- internal static void Break(int iteration, ParallelLoopStateFlags32 pflags)
- {
- int oldValue = ParallelLoopStateFlags.PLS_NONE;
-
- // Attempt to change state from "not stopped or broken or canceled or exceptional" to "broken".
- if (!pflags.AtomicLoopStateUpdate(ParallelLoopStateFlags.PLS_BROKEN,
- ParallelLoopStateFlags.PLS_STOPPED | ParallelLoopStateFlags.PLS_EXCEPTIONAL | ParallelLoopStateFlags.PLS_CANCELED,
- ref oldValue))
- {
-
- // If we were already stopped, we have a problem
- if ((oldValue & ParallelLoopStateFlags.PLS_STOPPED) != 0)
- {
- throw new InvalidOperationException(
- Environment.GetResourceString("ParallelState_Break_InvalidOperationException_BreakAfterStop"));
- }
- else
- {
- // Apparently we previously got cancelled or became exceptional. No action necessary
- return;
- }
- }
-
- // replace shared LowestBreakIteration with CurrentIteration, but only if CurrentIteration
- // is less than LowestBreakIteration.
- int oldLBI = pflags.m_lowestBreakIteration;
- if (iteration < oldLBI)
- {
- SpinWait wait = new SpinWait();
- while (Interlocked.CompareExchange(
- ref pflags.m_lowestBreakIteration,
- iteration,
- oldLBI) != oldLBI)
- {
- wait.SpinOnce();
- oldLBI = pflags.m_lowestBreakIteration;
- if (iteration > oldLBI) break;
- }
- }
-
- }
-
- // Helper method to avoid repeating Break() logic between ParallelState64 and ParallelState64<TLocal>
- internal static void Break(long iteration, ParallelLoopStateFlags64 pflags)
- {
- int oldValue = ParallelLoopStateFlags.PLS_NONE;
-
- // Attempt to change state from "not stopped or broken or canceled or exceptional" to "broken".
- if (!pflags.AtomicLoopStateUpdate(ParallelLoopStateFlags.PLS_BROKEN,
- ParallelLoopStateFlags.PLS_STOPPED | ParallelLoopStateFlags.PLS_EXCEPTIONAL | ParallelLoopStateFlags.PLS_CANCELED,
- ref oldValue))
- {
-
- // If we were already stopped, we have a problem
- if ((oldValue & ParallelLoopStateFlags.PLS_STOPPED) != 0)
- {
- throw new InvalidOperationException(
- Environment.GetResourceString("ParallelState_Break_InvalidOperationException_BreakAfterStop"));
- }
- else
- {
- // Apparently we previously got cancelled or became exceptional. No action necessary
- return;
- }
- }
-
- // replace shared LowestBreakIteration with CurrentIteration, but only if CurrentIteration
- // is less than LowestBreakIteration.
- long oldLBI = pflags.LowestBreakIteration;
- if (iteration < oldLBI)
- {
- SpinWait wait = new SpinWait();
- while (Interlocked.CompareExchange(
- ref pflags.m_lowestBreakIteration,
- iteration,
- oldLBI) != oldLBI)
- {
- wait.SpinOnce();
- oldLBI = pflags.LowestBreakIteration;
- if (iteration > oldLBI) break;
- }
- }
-
- }
- }
-
- internal class ParallelLoopState32 : ParallelLoopState
- {
- private ParallelLoopStateFlags32 m_sharedParallelStateFlags;
- private int m_currentIteration = 0;
-
- /// <summary>
- /// Internal constructor to ensure an instance isn't created by users.
- /// </summary>
- /// <param name="sharedParallelStateFlags">A flag shared among all threads participating
- /// in the execution of a certain loop.</param>
- internal ParallelLoopState32(ParallelLoopStateFlags32 sharedParallelStateFlags)
- : base(sharedParallelStateFlags)
- {
- m_sharedParallelStateFlags = sharedParallelStateFlags;
- }
-
- /// <summary>
- /// Tracks the current loop iteration for the owning task.
- /// This is used to compute whether or not the task should
- /// terminate early due to a Break() call.
- /// </summary>
- internal int CurrentIteration {
- get { return m_currentIteration; }
- set { m_currentIteration = value; }
- }
-
- /// <summary>
- /// Returns true if we should be exiting from the current iteration
- /// due to Stop(), Break() or exception.
- /// </summary>
- internal override bool InternalShouldExitCurrentIteration
- {
- get { return m_sharedParallelStateFlags.ShouldExitLoop(CurrentIteration); }
- }
-
- /// <summary>
- /// Returns the lowest iteration at which Break() has been called, or
- /// null if Break() has not yet been called.
- /// </summary>
- internal override long? InternalLowestBreakIteration
- {
- get {return m_sharedParallelStateFlags.NullableLowestBreakIteration; }
- }
-
- /// <summary>
- /// Communicates that parallel tasks should stop when they reach a specified iteration element.
- /// (which is CurrentIteration of the caller).
- /// </summary>
- /// <exception cref="T:System.InvalidOperationException">Break() called after Stop().</exception>
- /// <remarks>
- /// This is shared with all other concurrent threads in the system which are participating in the
- /// loop's execution. After calling Break(), no additional iterations will be executed on
- /// the current thread, and other worker threads will execute once they get beyond the calling iteration.
- /// </remarks>
- internal override void InternalBreak()
- {
- ParallelLoopState.Break(CurrentIteration, m_sharedParallelStateFlags);
- }
- }
-
- /// <summary>
- /// Allows independent iterations of a parallel loop to interact with other iterations.
- /// </summary>
- internal class ParallelLoopState64 : ParallelLoopState
- {
- private ParallelLoopStateFlags64 m_sharedParallelStateFlags;
- private long m_currentIteration = 0;
-
- /// <summary>
- /// Internal constructor to ensure an instance isn't created by users.
- /// </summary>
- /// <param name="sharedParallelStateFlags">A flag shared among all threads participating
- /// in the execution of a certain loop.</param>
- internal ParallelLoopState64(ParallelLoopStateFlags64 sharedParallelStateFlags)
- : base(sharedParallelStateFlags)
- {
- m_sharedParallelStateFlags = sharedParallelStateFlags;
- }
-
- /// <summary>
- /// Tracks the current loop iteration for the owning task.
- /// This is used to compute whether or not the task should
- /// terminate early due to a Break() call.
- /// </summary>
- internal long CurrentIteration
- {
- // No interlocks needed, because this value is only accessed in a single thread.
- get {return m_currentIteration;}
- set {m_currentIteration = value; }
- }
-
- /// <summary>
- /// Returns true if we should be exiting from the current iteration
- /// due to Stop(), Break() or exception.
- /// </summary>
- internal override bool InternalShouldExitCurrentIteration
- {
- get { return m_sharedParallelStateFlags.ShouldExitLoop(CurrentIteration); }
- }
-
- /// <summary>
- /// Returns the lowest iteration at which Break() has been called, or
- /// null if Break() has not yet been called.
- /// </summary>
- internal override long? InternalLowestBreakIteration
- {
- // We don't need to worry about torn read/write here because
- // ParallelStateFlags64.LowestBreakIteration property is protected
- // by an Interlocked.Read().
- get { return m_sharedParallelStateFlags.NullableLowestBreakIteration; }
- }
-
- /// <summary>
- /// Communicates that parallel tasks should stop when they reach a specified iteration element.
- /// (which is CurrentIteration of the caller).
- /// </summary>
- /// <exception cref="T:System.InvalidOperationException">Break() called after Stop().</exception>
- /// <remarks>
- /// Atomically sets shared StoppedBroken flag to BROKEN, then atomically sets shared
- /// LowestBreakIteration to CurrentIteration, but only if CurrentIteration is less than
- /// LowestBreakIteration.
- /// </remarks>
- internal override void InternalBreak()
- {
- ParallelLoopState.Break(CurrentIteration, m_sharedParallelStateFlags);
- }
-
- }
-
- /// <summary>
- /// State information that is common between ParallelStateFlags class
- /// and ParallelStateFlags64 class.
- /// </summary>
- internal class ParallelLoopStateFlags
- {
- internal static int PLS_NONE;
- internal static int PLS_EXCEPTIONAL = 1;
- internal static int PLS_BROKEN = 2;
- internal static int PLS_STOPPED = 4;
- internal static int PLS_CANCELED = 8;
-
- private volatile int m_LoopStateFlags = PLS_NONE;
-
- internal int LoopStateFlags
- {
- get { return m_LoopStateFlags; }
- }
-
- internal bool AtomicLoopStateUpdate(int newState, int illegalStates)
- {
- int oldState = 0;
- return AtomicLoopStateUpdate(newState, illegalStates, ref oldState);
- }
-
- internal bool AtomicLoopStateUpdate(int newState, int illegalStates, ref int oldState)
- {
- SpinWait sw = new SpinWait();
-
- do
- {
- oldState = m_LoopStateFlags;
- if ((oldState & illegalStates) != 0) return false;
- if (Interlocked.CompareExchange(ref m_LoopStateFlags, oldState | newState, oldState) == oldState)
- {
- return true;
- }
- sw.SpinOnce();
- } while (true);
-
- }
-
- internal void SetExceptional()
- {
- // we can set the exceptional flag regardless of the state of other bits.
- AtomicLoopStateUpdate(PLS_EXCEPTIONAL, PLS_NONE);
- }
-
- internal void Stop()
- {
- // disallow setting of PLS_STOPPED bit only if PLS_BROKEN was already set
- if (!AtomicLoopStateUpdate(PLS_STOPPED, PLS_BROKEN))
- {
- throw new InvalidOperationException(
- Environment.GetResourceString("ParallelState_Stop_InvalidOperationException_StopAfterBreak"));
- }
- }
-
- // Returns true if StoppedBroken is updated to PLS_CANCELED.
- internal bool Cancel()
- {
- // we can set the canceled flag regardless of the state of other bits.
- return (AtomicLoopStateUpdate(PLS_CANCELED, PLS_NONE));
- }
- }
-
- /// <summary>
- /// An internal class used to share accounting information in 32-bit versions
- /// of For()/ForEach() loops.
- /// </summary>
- internal class ParallelLoopStateFlags32 : ParallelLoopStateFlags
- {
- // Records the lowest iteration at which a Break() has been called,
- // or Int32.MaxValue if no break has been called. Used directly
- // by Break().
- internal volatile int m_lowestBreakIteration = Int32.MaxValue;
-
- // Not strictly necessary, but maintains consistency with ParallelStateFlags64
- internal int LowestBreakIteration
- {
- get { return m_lowestBreakIteration; }
- }
-
- // Does some processing to convert m_lowestBreakIteration to a long?.
- internal long? NullableLowestBreakIteration
- {
- get
- {
- if (m_lowestBreakIteration == Int32.MaxValue) return null;
- else
- {
- // protect against torn read of 64-bit value
- long rval = m_lowestBreakIteration;
- if (IntPtr.Size >= 8) return rval;
- else return Interlocked.Read(ref rval);
- }
- }
- }
-
-
- /// <summary>
- /// Lets the caller know whether or not to prematurely exit the For/ForEach loop.
- /// If this returns true, then exit the loop. Otherwise, keep going.
- /// </summary>
- /// <param name="CallerIteration">The caller's current iteration point
- /// in the loop.</param>
- /// <remarks>
- /// The loop should exit on any one of the following conditions:
- /// (1) Stop() has been called by one or more tasks.
- /// (2) An exception has been raised by one or more tasks.
- /// (3) Break() has been called by one or more tasks, and
- /// CallerIteration exceeds the (lowest) iteration at which
- /// Break() was called.
- /// (4) The loop was canceled.
- /// </remarks>
- internal bool ShouldExitLoop(int CallerIteration)
- {
- int flags = LoopStateFlags;
- return (flags != PLS_NONE && (
- ((flags & (PLS_EXCEPTIONAL | PLS_STOPPED | PLS_CANCELED)) != 0) ||
- (((flags & PLS_BROKEN) != 0) && (CallerIteration > LowestBreakIteration))));
- }
-
- // This lighter version of ShouldExitLoop will be used when the body type doesn't contain a state.
- // Since simpler bodies cannot stop or break, we can safely skip checks for those flags here.
- internal bool ShouldExitLoop()
- {
- int flags = LoopStateFlags;
- return ((flags != PLS_NONE) && ((flags & (PLS_EXCEPTIONAL | PLS_CANCELED)) != 0));
- }
- }
-
- /// <summary>
- /// An internal class used to share accounting information in 64-bit versions
- /// of For()/ForEach() loops.
- /// </summary>
- internal class ParallelLoopStateFlags64 : ParallelLoopStateFlags
- {
- // Records the lowest iteration at which a Break() has been called,
- // or Int64.MaxValue if no break has been called. Used directly
- // by Break().
- internal long m_lowestBreakIteration = Int64.MaxValue;
-
- // Performs a conditionally interlocked read of m_lowestBreakIteration.
- internal long LowestBreakIteration
- {
- get
- {
- if (IntPtr.Size >= 8) return m_lowestBreakIteration;
- else return Interlocked.Read(ref m_lowestBreakIteration);
- }
- }
-
- // Does some processing to convert m_lowestBreakIteration to a long?.
- internal long? NullableLowestBreakIteration
- {
- get
- {
- if (m_lowestBreakIteration == Int64.MaxValue) return null;
- else
- {
- if (IntPtr.Size >= 8) return m_lowestBreakIteration;
- else return Interlocked.Read(ref m_lowestBreakIteration);
- }
- }
- }
-
- /// <summary>
- /// Lets the caller know whether or not to prematurely exit the For/ForEach loop.
- /// If this returns true, then exit the loop. Otherwise, keep going.
- /// </summary>
- /// <param name="CallerIteration">The caller's current iteration point
- /// in the loop.</param>
- /// <remarks>
- /// The loop should exit on any one of the following conditions:
- /// (1) Stop() has been called by one or more tasks.
- /// (2) An exception has been raised by one or more tasks.
- /// (3) Break() has been called by one or more tasks, and
- /// CallerIteration exceeds the (lowest) iteration at which
- /// Break() was called.
- /// (4) The loop has been canceled.
- /// </remarks>
- internal bool ShouldExitLoop(long CallerIteration)
- {
- int flags = LoopStateFlags;
- return (flags != PLS_NONE && (
- ((flags & (PLS_EXCEPTIONAL | PLS_STOPPED | PLS_CANCELED)) != 0) ||
- (((flags & PLS_BROKEN) != 0) && (CallerIteration > LowestBreakIteration))));
- }
-
- // This lighter version of ShouldExitLoop will be used when the body type doesn't contain a state.
- // Since simpler bodies cannot stop or break, we can safely skip checks for those flags here.
- internal bool ShouldExitLoop()
- {
- int flags = LoopStateFlags;
- return ((flags != PLS_NONE) && ((flags & (PLS_EXCEPTIONAL | PLS_CANCELED)) != 0));
- }
- }
-
- /// <summary>
- /// Provides completion status on the execution of a <see cref="Parallel"/> loop.
- /// </summary>
- /// <remarks>
- /// If <see cref="IsCompleted"/> returns true, then the loop ran to completion, such that all iterations
- /// of the loop were executed. If <see cref="IsCompleted"/> returns false and <see
- /// cref="LowestBreakIteration"/> returns null, a call to <see
- /// cref="System.Threading.Tasks.ParallelLoopState.Stop"/> was used to end the loop prematurely. If <see
- /// cref="IsCompleted"/> returns false and <see cref="LowestBreakIteration"/> returns a non-null integral
- /// value, <see cref="System.Threading.Tasks.ParallelLoopState.Break()"/> was used to end the loop prematurely.
- /// </remarks>
- public struct ParallelLoopResult
- {
- internal bool m_completed;
- internal long? m_lowestBreakIteration;
-
- /// <summary>
- /// Gets whether the loop ran to completion, such that all iterations of the loop were executed
- /// and the loop didn't receive a request to end prematurely.
- /// </summary>
- public bool IsCompleted { get { return m_completed; } }
-
- /// <summary>
- /// Gets the index of the lowest iteration from which <see
- /// cref="System.Threading.Tasks.ParallelLoopState.Break()"/>
- /// was called.
- /// </summary>
- /// <remarks>
- /// If <see cref="System.Threading.Tasks.ParallelLoopState.Break()"/> was not employed, this property will
- /// return null.
- /// </remarks>
- public long? LowestBreakIteration { get { return m_lowestBreakIteration; } }
- }
-
-}
-
-#pragma warning restore 0420
diff --git a/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs b/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs
deleted file mode 100644
index 49f61a6..0000000
--- a/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs
+++ /dev/null
@@ -1,279 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
-//
-//
-//
-// Implements the algorithm for distributing loop indices to parallel loop workers
-//
-// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-
-using System;
-using System.Threading;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-
-#pragma warning disable 0420
-
-namespace System.Threading.Tasks
-{
- /// <summary>
- /// Represents an index range
- /// </summary>
- internal struct IndexRange
- {
- // the From and To values for this range. These do not change.
- internal long m_nFromInclusive;
- internal long m_nToExclusive;
-
- // The shared index, stored as the offset from nFromInclusive. Using an offset rather than the actual
- // value saves us from overflows that can happen due to multiple workers racing to increment this.
- // All updates to this field need to be interlocked.
- internal volatile Shared<long> m_nSharedCurrentIndexOffset;
-
- // to be set to 1 by the worker that finishes this range. It's OK to do a non-interlocked write here.
- internal int m_bRangeFinished;
- }
-
-
- /// <summary>
- /// The RangeWorker struct wraps the state needed by a task that services the parallel loop
- /// </summary>
- internal struct RangeWorker
- {
- // reference to the IndexRange array allocated by the range manager
- internal readonly IndexRange[] m_indexRanges;
-
- // index of the current index range that this worker is grabbing chunks from
- internal int m_nCurrentIndexRange;
-
- // the step for this loop. Duplicated here for quick access (rather than jumping to rangemanager)
- internal long m_nStep;
-
- // increment value is the current amount that this worker will use
- // to increment the shared index of the range it's working on
- internal long m_nIncrementValue;
-
- // the increment value is doubled each time this worker finds work, and is capped at this value
- internal readonly long m_nMaxIncrementValue;
-
- /// <summary>
- /// Initializes a RangeWorker struct
- /// </summary>
- internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep)
- {
- m_indexRanges = ranges;
- m_nCurrentIndexRange = nInitialRange;
- m_nStep = nStep;
-
- m_nIncrementValue = nStep;
-
- m_nMaxIncrementValue = Parallel.DEFAULT_LOOP_STRIDE * nStep;
- }
-
- /// <summary>
- /// Implements the core work search algorithm that will be used for this range worker.
- /// </summary>
- ///
- /// Usage pattern is:
- /// 1) the thread associated with this rangeworker calls FindNewWork
- /// 2) if we return true, the worker uses the nFromInclusiveLocal and nToExclusiveLocal values
- /// to execute the sequential loop
- /// 3) if we return false it means there is no more work left. It's time to quit.
- ///
- internal bool FindNewWork(out long nFromInclusiveLocal, out long nToExclusiveLocal)
- {
- // since we iterate over index ranges circularly, we will use the
- // count of visited ranges as our exit condition
- int numIndexRangesToVisit = m_indexRanges.Length;
-
- do
- {
- // local snap to save array access bounds checks in places where we only read fields
- IndexRange currentRange = m_indexRanges[m_nCurrentIndexRange];
-
- if (currentRange.m_bRangeFinished == 0)
- {
- if (m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset == null)
- {
- Interlocked.CompareExchange(ref m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset, new Shared<long>(0), null);
- }
-
- // this access needs to be on the array slot
- long nMyOffset = Interlocked.Add(ref m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset.Value,
- m_nIncrementValue) - m_nIncrementValue;
-
- if (currentRange.m_nToExclusive - currentRange.m_nFromInclusive > nMyOffset)
- {
- // we found work
-
- nFromInclusiveLocal = currentRange.m_nFromInclusive + nMyOffset;
- nToExclusiveLocal = nFromInclusiveLocal + m_nIncrementValue;
-
- // Check for going past end of range, or wrapping
- if ( (nToExclusiveLocal > currentRange.m_nToExclusive) || (nToExclusiveLocal < currentRange.m_nFromInclusive) )
- {
- nToExclusiveLocal = currentRange.m_nToExclusive;
- }
-
- // We will double our unit of increment until it reaches the maximum.
- if (m_nIncrementValue < m_nMaxIncrementValue)
- {
- m_nIncrementValue *= 2;
- if (m_nIncrementValue > m_nMaxIncrementValue)
- {
- m_nIncrementValue = m_nMaxIncrementValue;
- }
- }
-
- return true;
- }
- else
- {
- // this index range is completed, mark it so that others can skip it quickly
- Interlocked.Exchange(ref m_indexRanges[m_nCurrentIndexRange].m_bRangeFinished, 1);
- }
- }
-
- // move on to the next index range, in circular order.
- m_nCurrentIndexRange = (m_nCurrentIndexRange + 1) % m_indexRanges.Length;
- numIndexRangesToVisit--;
-
- } while (numIndexRangesToVisit > 0);
- // we've visited all index ranges possible => there's no work remaining
-
- nFromInclusiveLocal = 0;
- nToExclusiveLocal = 0;
-
- return false;
- }
-
-
- /// <summary>
- /// 32 bit integer version of FindNewWork. Assumes the ranges were initialized with 32 bit values.
- /// </summary>
- internal bool FindNewWork32(out int nFromInclusiveLocal32, out int nToExclusiveLocal32)
- {
- long nFromInclusiveLocal;
- long nToExclusiveLocal;
-
- bool bRetVal = FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal);
-
- Debug.Assert((nFromInclusiveLocal <= Int32.MaxValue) && (nFromInclusiveLocal >= Int32.MinValue) &&
- (nToExclusiveLocal <= Int32.MaxValue) && (nToExclusiveLocal >= Int32.MinValue));
-
- // convert to 32 bit before returning
- nFromInclusiveLocal32 = (int)nFromInclusiveLocal;
- nToExclusiveLocal32 = (int)nToExclusiveLocal;
-
- return bRetVal;
- }
- }
-
-
- /// <summary>
- /// Represents the entire loop operation, keeping track of workers and ranges.
- /// </summary>
- ///
- /// The usage pattern is:
- /// 1) The Parallel loop entry function (ForWorker) creates an instance of this class
- /// 2) Every thread joining to service the parallel loop calls RegisterWorker to grab a
- /// RangeWorker struct to wrap the state it will need to find and execute work,
- /// and they keep interacting with that struct until the end of the loop
- internal class RangeManager
- {
- internal readonly IndexRange[] m_indexRanges;
-
- internal int m_nCurrentIndexRangeToAssign;
- internal long m_nStep;
-
- /// <summary>
- /// Initializes a RangeManager with the given loop parameters, and the desired number of outer ranges
- /// </summary>
- internal RangeManager(long nFromInclusive, long nToExclusive, long nStep, int nNumExpectedWorkers)
- {
- m_nCurrentIndexRangeToAssign = 0;
- m_nStep = nStep;
-
- // Our signed math breaks down w/ nNumExpectedWorkers == 1. So change it to 2.
- if (nNumExpectedWorkers == 1)
- nNumExpectedWorkers = 2;
-
- //
- // calculate the size of each index range
- //
-
- ulong uSpan = (ulong)(nToExclusive - nFromInclusive);
- ulong uRangeSize = uSpan / (ulong) nNumExpectedWorkers; // rough estimate first
-
- uRangeSize -= uRangeSize % (ulong) nStep; // snap to multiples of nStep
- // otherwise index range transitions will derail us from nStep
-
- if (uRangeSize == 0)
- {
- uRangeSize = (ulong) nStep;
- }
-
- //
- // find the actual number of index ranges we will need
- //
- Debug.Assert((uSpan / uRangeSize) < Int32.MaxValue);
-
- int nNumRanges = (int)(uSpan / uRangeSize);
-
- if (uSpan % uRangeSize != 0)
- {
- nNumRanges++;
- }
-
-
- // Convert to signed so the rest of the logic works.
- // Should be fine so long as uRangeSize < Int64.MaxValue, which we guaranteed by setting #workers >= 2.
- long nRangeSize = (long)uRangeSize;
-
- // allocate the array of index ranges
- m_indexRanges = new IndexRange[nNumRanges];
-
- long nCurrentIndex = nFromInclusive;
- for (int i = 0; i < nNumRanges; i++)
- {
- // the fromInclusive of the new index range is always on nCurrentIndex
- m_indexRanges[i].m_nFromInclusive = nCurrentIndex;
- m_indexRanges[i].m_nSharedCurrentIndexOffset = null;
- m_indexRanges[i].m_bRangeFinished = 0;
-
- // now increment it to find the toExclusive value for our range
- nCurrentIndex += nRangeSize;
-
- // detect integer overflow or range overage and snap to nToExclusive
- if (nCurrentIndex < nCurrentIndex - nRangeSize ||
- nCurrentIndex > nToExclusive)
- {
- // this should only happen at the last index
- Debug.Assert(i == nNumRanges - 1);
-
- nCurrentIndex = nToExclusive;
- }
-
- // now that the end point of the new range is calculated, assign it.
- m_indexRanges[i].m_nToExclusive = nCurrentIndex;
- }
- }
-
- /// <summary>
- /// The function that needs to be called by each new worker thread servicing the parallel loop
- /// in order to get a RangeWorker struct that wraps the state for finding and executing indices
- /// </summary>
- internal RangeWorker RegisterNewWorker()
- {
- Debug.Assert(m_indexRanges != null && m_indexRanges.Length != 0);
-
- int nInitialRange = (Interlocked.Increment(ref m_nCurrentIndexRangeToAssign) - 1) % m_indexRanges.Length;
-
- return new RangeWorker(m_indexRanges, nInitialRange, m_nStep);
- }
- }
-}
-#pragma warning restore 0420
diff --git a/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs b/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
index 6b9dfbb..545bf9a 100644
--- a/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
@@ -52,11 +52,6 @@ namespace System.Threading.Tasks
/// <summary>Gets the number of items in the collection.</summary>
/// <remarks>In many implementations, this method will not be thread-safe.</remarks>
int Count { get; }
-
- /// <summary>A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object.</summary>
- /// <param name="syncObj">The sync object used to lock</param>
- /// <returns>The collection count</returns>
- int GetCountSafe(object syncObj);
}
/// <summary>
@@ -80,10 +75,6 @@ namespace System.Threading.Tasks
/// <summary>Gets the number of items in the collection.</summary>
int IProducerConsumerQueue<T>.Count { get { return base.Count; } }
-
- /// <summary>A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object.</summary>
- /// <remarks>ConcurrentQueue.Count is thread safe, no need to acquire the lock.</remarks>
- int IProducerConsumerQueue<T>.GetCountSafe(object syncObj) { return base.Count; }
}
/// <summary>
@@ -260,143 +251,6 @@ namespace System.Threading.Tasks
return true;
}
- /// <summary>Attempts to peek at an item in the queue.</summary>
- /// <param name="result">The peeked item.</param>
- /// <returns>true if an item could be peeked; otherwise, false.</returns>
- public bool TryPeek(out T result)
- {
- Segment segment = m_head;
- var array = segment.m_array;
- int first = segment.m_state.m_first; // local copy to avoid multiple volatile reads
-
- // Fast path: there's obviously data available in the current segment
- if (first != segment.m_state.m_lastCopy)
- {
- result = array[first];
- return true;
- }
- // Slow path: there may not be data available in the current segment
- else return TryPeekSlow(ref segment, ref array, out result);
- }
-
- /// <summary>Attempts to peek at an item in the queue.</summary>
- /// <param name="array">The array from which the item is peeked.</param>
- /// <param name="segment">The segment from which the item is peeked.</param>
- /// <param name="result">The peeked item.</param>
- /// <returns>true if an item could be peeked; otherwise, false.</returns>
- private bool TryPeekSlow(ref Segment segment, ref T[] array, out T result)
- {
- Contract.Requires(segment != null, "Expected a non-null segment.");
- Contract.Requires(array != null, "Expected a non-null item array.");
-
- if (segment.m_state.m_last != segment.m_state.m_lastCopy)
- {
- segment.m_state.m_lastCopy = segment.m_state.m_last;
- return TryPeek(out result); // will only recur once for this peek operation
- }
-
- if (segment.m_next != null && segment.m_state.m_first == segment.m_state.m_last)
- {
- segment = segment.m_next;
- array = segment.m_array;
- m_head = segment;
- }
-
- var first = segment.m_state.m_first; // local copy to avoid extraneous volatile reads
-
- if (first == segment.m_state.m_last)
- {
- result = default(T);
- return false;
- }
-
- result = array[first];
- return true;
- }
-
- /// <summary>Attempts to dequeue an item from the queue.</summary>
- /// <param name="predicate">The predicate that must return true for the item to be dequeued. If null, all items implicitly return true.</param>
- /// <param name="result">The dequeued item.</param>
- /// <returns>true if an item could be dequeued; otherwise, false.</returns>
- public bool TryDequeueIf(Predicate<T> predicate, out T result)
- {
- Segment segment = m_head;
- var array = segment.m_array;
- int first = segment.m_state.m_first; // local copy to avoid multiple volatile reads
-
- // Fast path: there's obviously data available in the current segment
- if (first != segment.m_state.m_lastCopy)
- {
- result = array[first];
- if (predicate == null || predicate(result))
- {
- array[first] = default(T); // Clear the slot to release the element
- segment.m_state.m_first = (first + 1) & (array.Length - 1);
- return true;
- }
- else
- {
- result = default(T);
- return false;
- }
- }
- // Slow path: there may not be data available in the current segment
- else return TryDequeueIfSlow(predicate, ref segment, ref array, out result);
- }
-
- /// <summary>Attempts to dequeue an item from the queue.</summary>
- /// <param name="predicate">The predicate that must return true for the item to be dequeued. If null, all items implicitly return true.</param>
- /// <param name="array">The array from which the item was dequeued.</param>
- /// <param name="segment">The segment from which the item was dequeued.</param>
- /// <param name="result">The dequeued item.</param>
- /// <returns>true if an item could be dequeued; otherwise, false.</returns>
- private bool TryDequeueIfSlow(Predicate<T> predicate, ref Segment segment, ref T[] array, out T result)
- {
- Contract.Requires(segment != null, "Expected a non-null segment.");
- Contract.Requires(array != null, "Expected a non-null item array.");
-
- if (segment.m_state.m_last != segment.m_state.m_lastCopy)
- {
- segment.m_state.m_lastCopy = segment.m_state.m_last;
- return TryDequeueIf(predicate, out result); // will only recur once for this dequeue operation
- }
-
- if (segment.m_next != null && segment.m_state.m_first == segment.m_state.m_last)
- {
- segment = segment.m_next;
- array = segment.m_array;
- m_head = segment;
- }
-
- var first = segment.m_state.m_first; // local copy to avoid extraneous volatile reads
-
- if (first == segment.m_state.m_last)
- {
- result = default(T);
- return false;
- }
-
- result = array[first];
- if (predicate == null || predicate(result))
- {
- array[first] = default(T); // Clear the slot to release the element
- segment.m_state.m_first = (first + 1) & (segment.m_array.Length - 1);
- segment.m_state.m_lastCopy = segment.m_state.m_last; // Refresh m_lastCopy to ensure that m_first has not passed m_lastCopy
- return true;
- }
- else
- {
- result = default(T);
- return false;
- }
- }
-
- public void Clear()
- {
- T ignored;
- while (TryDequeue(out ignored)) ;
- }
-
/// <summary>Gets whether the collection is currently empty.</summary>
/// <remarks>WARNING: This should not be used concurrently without further vetting.</remarks>
public bool IsEmpty
@@ -452,17 +306,6 @@ namespace System.Threading.Tasks
}
}
- /// <summary>A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object.</summary>
- /// <remarks>The Count is not thread safe, so we need to acquire the lock.</remarks>
- int IProducerConsumerQueue<T>.GetCountSafe(object syncObj)
- {
- Debug.Assert(syncObj != null, "The syncObj parameter is null.");
- lock (syncObj)
- {
- return Count;
- }
- }
-
/// <summary>A segment in the queue containing one or more items.</summary>
[StructLayout(LayoutKind.Sequential)]
private sealed class Segment
@@ -520,23 +363,9 @@ namespace System.Threading.Tasks
Contract.Requires(queue != null, "Expected a non-null queue.");
m_queue = queue;
}
-
- /// <summary>Gets the contents of the list.</summary>
- [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
- public T[] Items
- {
- get
- {
- List<T> list = new List<T>();
- foreach (T item in m_queue)
- list.Add(item);
- return list.ToArray();
- }
- }
}
}
-
/// <summary>A placeholder class for common padding constants and eventually routines.</summary>
static class PaddingHelpers
{
diff --git a/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs b/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs
index 325aa91..12cc1da 100644
--- a/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs
@@ -14,7 +14,6 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
-using System.Security.Permissions;
using System.Runtime.CompilerServices;
namespace System.Threading.Tasks
@@ -61,17 +60,6 @@ namespace System.Threading.Tasks
/// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
private TplEtwProvider() { }
- /// <summary>Type of a fork/join operation.</summary>
- public enum ForkJoinOperationType
- {
- /// <summary>Parallel.Invoke.</summary>
- ParallelInvoke=1,
- /// <summary>Parallel.For.</summary>
- ParallelFor=2,
- /// <summary>Parallel.ForEach.</summary>
- ParallelForEach=3
- }
-
/// <summary>Configured behavior of a task wait operation.</summary>
public enum TaskWaitBehavior : int
{
@@ -203,195 +191,6 @@ namespace System.Threading.Tasks
//-----------------------------------------------------------------------------------
//
- // Parallel Events
- //
-
- #region ParallelLoopBegin
- /// <summary>
- /// Denotes the entry point for a Parallel.For or Parallel.ForEach loop
- /// </summary>
- /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
- /// <param name="OriginatingTaskID">The task ID.</param>
- /// <param name="ForkJoinContextID">The loop ID.</param>
- /// <param name="OperationType">The kind of fork/join operation.</param>
- /// <param name="InclusiveFrom">The lower bound of the loop.</param>
- /// <param name="ExclusiveTo">The upper bound of the loop.</param>
- [Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive,
- Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)]
- public void ParallelLoopBegin(
- int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
- long InclusiveFrom, long ExclusiveTo)
- {
- if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
- {
- // There is no explicit WriteEvent() overload matching this event's fields. Therefore calling
- // WriteEvent() would hit the "params" overload, which leads to an object allocation every time
- // this event is fired. To prevent that problem we will call WriteEventCore(), which works with
- // a stack based EventData array populated with the event fields.
- unsafe
- {
- EventData* eventPayload = stackalloc EventData[6];
-
- eventPayload[0].Size = sizeof(int);
- eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
- eventPayload[1].Size = sizeof(int);
- eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
- eventPayload[2].Size = sizeof(int);
- eventPayload[2].DataPointer = ((IntPtr) (&ForkJoinContextID));
- eventPayload[3].Size = sizeof(int);
- eventPayload[3].DataPointer = ((IntPtr) (&OperationType));
- eventPayload[4].Size = sizeof(long);
- eventPayload[4].DataPointer = ((IntPtr) (&InclusiveFrom));
- eventPayload[5].Size = sizeof(long);
- eventPayload[5].DataPointer = ((IntPtr) (&ExclusiveTo));
-
- WriteEventCore(PARALLELLOOPBEGIN_ID, 6, eventPayload);
- }
- }
- }
- #endregion
-
- #region ParallelLoopEnd
- /// <summary>
- /// Denotes the end of a Parallel.For or Parallel.ForEach loop.
- /// </summary>
- /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
- /// <param name="OriginatingTaskID">The task ID.</param>
- /// <param name="ForkJoinContextID">The loop ID.</param>
- /// <param name="TotalIterations">the total number of iterations processed.</param>
- [Event(PARALLELLOOPEND_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Stop)]
- public void ParallelLoopEnd(
- int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int ForkJoinContextID, long TotalIterations)
- {
- if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
- {
- // There is no explicit WriteEvent() overload matching this event's fields.
- // Therefore calling WriteEvent() would hit the "params" overload, which leads to an object allocation every time this event is fired.
- // To prevent that problem we will call WriteEventCore(), which works with a stack based EventData array populated with the event fields
- unsafe
- {
- EventData* eventPayload = stackalloc EventData[4];
-
- eventPayload[0].Size = sizeof(int);
- eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
- eventPayload[1].Size = sizeof(int);
- eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
- eventPayload[2].Size = sizeof(int);
- eventPayload[2].DataPointer = ((IntPtr) (&ForkJoinContextID));
- eventPayload[3].Size = sizeof(long);
- eventPayload[3].DataPointer = ((IntPtr) (&TotalIterations));
-
- WriteEventCore(PARALLELLOOPEND_ID, 4, eventPayload);
- }
- }
- }
- #endregion
-
- #region ParallelInvokeBegin
- /// <summary>Denotes the entry point for a Parallel.Invoke call.</summary>
- /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
- /// <param name="OriginatingTaskID">The task ID.</param>
- /// <param name="ForkJoinContextID">The invoke ID.</param>
- /// <param name="OperationType">The kind of fork/join operation.</param>
- /// <param name="ActionCount">The number of actions being invoked.</param>
- [Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive,
- Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)]
- public void ParallelInvokeBegin(
- int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
- int ActionCount)
- {
- if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
- {
- // There is no explicit WriteEvent() overload matching this event's fields.
- // Therefore calling WriteEvent() would hit the "params" overload, which leads to an object allocation every time this event is fired.
- // To prevent that problem we will call WriteEventCore(), which works with a stack based EventData array populated with the event fields
- unsafe
- {
- EventData* eventPayload = stackalloc EventData[5];
-
- eventPayload[0].Size = sizeof(int);
- eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
- eventPayload[1].Size = sizeof(int);
- eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
- eventPayload[2].Size = sizeof(int);
- eventPayload[2].DataPointer = ((IntPtr) (&ForkJoinContextID));
- eventPayload[3].Size = sizeof(int);
- eventPayload[3].DataPointer = ((IntPtr) (&OperationType));
- eventPayload[4].Size = sizeof(int);
- eventPayload[4].DataPointer = ((IntPtr) (&ActionCount));
-
- WriteEventCore(PARALLELINVOKEBEGIN_ID, 5, eventPayload);
- }
- }
- }
- #endregion
-
- #region ParallelInvokeEnd
- /// <summary>
- /// Denotes the exit point for a Parallel.Invoke call.
- /// </summary>
- /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
- /// <param name="OriginatingTaskID">The task ID.</param>
- /// <param name="ForkJoinContextID">The invoke ID.</param>
- [Event(PARALLELINVOKEEND_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Stop)]
- public void ParallelInvokeEnd(
- int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int ForkJoinContextID)
- {
- if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
- {
- WriteEvent(PARALLELINVOKEEND_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
- }
- }
- #endregion
-
- #region ParallelFork
- /// <summary>
- /// Denotes the start of an individual task that's part of a fork/join context.
- /// Before this event is fired, the start of the new fork/join context will be marked
- /// with another event that declares a unique context ID.
- /// </summary>
- /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
- /// <param name="OriginatingTaskID">The task ID.</param>
- /// <param name="ForkJoinContextID">The invoke ID.</param>
- [Event(PARALLELFORK_ID, Level = EventLevel.Verbose, ActivityOptions=EventActivityOptions.Recursive,
- Task = TplEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Start)]
- public void ParallelFork(
- int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int ForkJoinContextID)
- {
- if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Parallel))
- {
- WriteEvent(PARALLELFORK_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
- }
- }
- #endregion
-
- #region ParallelJoin
- /// <summary>
- /// Denotes the end of an individual task that's part of a fork/join context.
- /// This should match a previous ParallelFork event with a matching "OriginatingTaskID"
- /// </summary>
- /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
- /// <param name="OriginatingTaskID">The task ID.</param>
- /// <param name="ForkJoinContextID">The invoke ID.</param>
- [Event(PARALLELJOIN_ID, Level = EventLevel.Verbose, Task = TplEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Stop)]
- public void ParallelJoin(
- int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int ForkJoinContextID)
- {
- if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Parallel))
- {
- WriteEvent(PARALLELJOIN_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
- }
- }
- #endregion
-
- //-----------------------------------------------------------------------------------
- //
// Task Events
//
@@ -512,7 +311,7 @@ namespace System.Threading.Tasks
Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
public void TaskWaitBegin(
int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
- int TaskID, TaskWaitBehavior Behavior, int ContinueWithTaskID, int appDomain)
+ int TaskID, TaskWaitBehavior Behavior, int ContinueWithTaskID)
{
if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
{
@@ -534,8 +333,10 @@ namespace System.Threading.Tasks
Guid childActivityId = CreateGuidForTaskID(TaskID);
WriteEventWithRelatedActivityIdCore(TASKWAITBEGIN_ID, &childActivityId, 5, eventPayload);
}
- else
+ else
+ {
WriteEventCore(TASKWAITBEGIN_ID, 5, eventPayload);
+ }
}
}
}
@@ -688,7 +489,7 @@ namespace System.Threading.Tasks
}
}
- [NonEvent, System.Security.SecuritySafeCritical]
+ [NonEvent]
unsafe public void RunningContinuation(int TaskID, object Object) { RunningContinuation(TaskID, (long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref Object))); }
[Event(20, Keywords = Keywords.Debug)]
private void RunningContinuation(int TaskID, long Object)
@@ -697,7 +498,7 @@ namespace System.Threading.Tasks
WriteEvent(20, TaskID, Object);
}
- [NonEvent, System.Security.SecuritySafeCritical]
+ [NonEvent]
unsafe public void RunningContinuationList(int TaskID, int Index, object Object) { RunningContinuationList(TaskID, Index, (long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref Object))); }
[Event(21, Keywords = Keywords.Debug)]
@@ -707,9 +508,6 @@ namespace System.Threading.Tasks
WriteEvent(21, TaskID, Index, Object);
}
- [Event(22, Keywords = Keywords.Debug)]
- public void DebugMessage(string Message) { WriteEvent(22, Message); }
-
[Event(23, Keywords = Keywords.Debug)]
public void DebugFacilityMessage(string Facility, string Message) { WriteEvent(23, Facility, Message); }
diff --git a/src/mscorlib/src/System/Threading/Tasks/Task.cs b/src/mscorlib/src/System/Threading/Tasks/Task.cs
index cf081f7..7013c5c 100644
--- a/src/mscorlib/src/System/Threading/Tasks/Task.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/Task.cs
@@ -18,7 +18,6 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.ExceptionServices;
using System.Security;
-using System.Security.Permissions;
using System.Threading;
using System.Diagnostics;
using System.Diagnostics.Contracts;
@@ -147,7 +146,6 @@ namespace System.Threading.Tasks
private static StackGuard t_stackGuard; // The stack guard object for this thread
internal static int s_taskIdCounter; //static counter used to generate unique task IDs
- private readonly static TaskFactory s_factory = new TaskFactory();
private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested
@@ -365,12 +363,9 @@ namespace System.Threading.Tasks
/// </summary>
/// <param name="action">The delegate that represents the code to execute in the Task.</param>
/// <exception cref="T:System.ArgumentNullException">The <paramref name="action"/> argument is null.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action action)
: this(action, null, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -383,12 +378,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action action, CancellationToken cancellationToken)
: this(action, null, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -406,12 +398,9 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action action, TaskCreationOptions creationOptions)
: this(action, null, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -433,12 +422,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(action, null, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
@@ -450,12 +436,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="action"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action<object> action, object state)
: this(action, state, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -470,12 +453,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action<object> action, object state, CancellationToken cancellationToken)
: this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -494,12 +474,9 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
: this(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -522,19 +499,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
- }
-
- internal Task(Action<object> action, object state, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
- : this(action, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
- {
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -557,10 +524,8 @@ namespace System.Threading.Tasks
}
Contract.EndContractBlock();
- // Keep a link to your parent if: (A) You are attached, or (B) you are self-replicating.
- if (parent != null &&
- ((creationOptions & TaskCreationOptions.AttachedToParent) != 0 ||
- (internalOptions & InternalTaskOptions.SelfReplicating) != 0))
+ // Keep a link to the parent if attached
+ if (parent != null && (creationOptions & TaskCreationOptions.AttachedToParent) != 0)
{
EnsureContingentPropertiesInitializedUnsafe().m_parent = parent;
}
@@ -586,6 +551,10 @@ namespace System.Threading.Tasks
m_stateObject = state;
m_taskScheduler = scheduler;
+ Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
+ "Captured an ExecutionContext when one was already captured.");
+ CapturedContext = ExecutionContext.Capture();
+
// Check for validity of options
if ((creationOptions &
~(TaskCreationOptions.AttachedToParent |
@@ -602,22 +571,13 @@ namespace System.Threading.Tasks
// Check the validity of internalOptions
int illegalInternalOptions =
(int) (internalOptions &
- ~(InternalTaskOptions.SelfReplicating |
- InternalTaskOptions.ChildReplica |
- InternalTaskOptions.PromiseTask |
+ ~(InternalTaskOptions.PromiseTask |
InternalTaskOptions.ContinuationTask |
InternalTaskOptions.LazyCancellation |
InternalTaskOptions.QueuedByRuntime));
Debug.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options");
#endif
- // Throw exception if the user specifies both LongRunning and SelfReplicating
- if (((creationOptions & TaskCreationOptions.LongRunning) != 0) &&
- ((internalOptions & InternalTaskOptions.SelfReplicating) != 0))
- {
- ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_ctor_LRandSR);
- }
-
// Assign options to m_stateAndOptionsFlag.
Debug.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags");
Debug.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits");
@@ -648,9 +608,7 @@ namespace System.Threading.Tasks
// we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags
if (cancellationToken.CanBeCanceled)
{
- Debug.Assert((internalOptions &
- (InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating | InternalTaskOptions.ContinuationTask)) == 0,
- "TaskConstructorCore: Did not expect to see cancelable token for replica/replicating or continuation task.");
+ Debug.Assert((internalOptions & InternalTaskOptions.ContinuationTask) == 0, "TaskConstructorCore: Did not expect to see cancelable token for continuation task.");
AssignCancellationToken(cancellationToken, null, null);
}
@@ -757,24 +715,6 @@ namespace System.Threading.Tasks
}
}
-
- /// <summary>
- /// Captures the ExecutionContext so long as flow isn't suppressed.
- /// </summary>
- /// <param name="stackMark">A stack crawl mark pointing to the frame of the caller.</param>
-
- internal void PossiblyCaptureContext(ref StackCrawlMark stackMark)
- {
- Debug.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
- "Captured an ExecutionContext when one was already captured.");
-
- // In the legacy .NET 3.5 build, we don't have the optimized overload of Capture()
- // available, so we call the parameterless overload.
- CapturedContext = ExecutionContext.Capture(
- ref stackMark,
- ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
- }
-
// Internal property to process TaskCreationOptions access and mutation.
internal TaskCreationOptions Options
{
@@ -989,16 +929,14 @@ namespace System.Threading.Tasks
/// </summary>
internal void AddNewChild()
{
- Debug.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");
+ Debug.Assert(Task.InternalCurrent == this, "Task.AddNewChild(): Called from an external context");
var props = EnsureContingentPropertiesInitialized();
- if (props.m_completionCountdown == 1 && !IsSelfReplicatingRoot)
+ if (props.m_completionCountdown == 1)
{
// A count of 1 indicates so far there was only the parent, and this is the first child task
// Single kid => no fuss about who else is accessing the count. Let's save ourselves 100 cycles
- // We exclude self replicating root tasks from this optimization, because further child creation can take place on
- // other cores and with bad enough timing this write may not be visible to them.
props.m_completionCountdown++;
}
else
@@ -1264,7 +1202,7 @@ namespace System.Threading.Tasks
// Implicitly converts action to object and handles the meat of the StartNew() logic.
internal static Task InternalStartNew(
Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
- TaskCreationOptions options, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark)
+ TaskCreationOptions options, InternalTaskOptions internalOptions)
{
// Validate arguments.
if (scheduler == null)
@@ -1276,7 +1214,6 @@ namespace System.Threading.Tasks
// Create and schedule the task. This throws an InvalidOperationException if already shut down.
// Here we add the InternalTaskOptions.QueuedByRuntime to the internalOptions, so that TaskConstructorCore can skip the cancellation token registration
Task t = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
- t.PossiblyCaptureContext(ref stackMark);
t.ScheduleAndStart(false);
return t;
@@ -1615,23 +1552,10 @@ namespace System.Threading.Tasks
/// of <see cref="System.Threading.Tasks.TaskFactory"/>, as would result from using
/// the default constructor on TaskFactory.
/// </remarks>
- public static TaskFactory Factory { get { return s_factory; } }
-
- /// <summary>A task that's already been completed successfully.</summary>
- private static Task s_completedTask;
+ public static TaskFactory Factory { get; } = new TaskFactory();
/// <summary>Gets a task that's already been completed successfully.</summary>
- /// <remarks>May not always return the same instance.</remarks>
- public static Task CompletedTask
- {
- get
- {
- var completedTask = s_completedTask;
- if (completedTask == null)
- s_completedTask = completedTask = new Task(false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); // benign initialization race condition
- return completedTask;
- }
- }
+ public static Task CompletedTask { get; } = new Task(false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
/// <summary>
/// Provides an event that can be used to wait for completion.
@@ -1663,35 +1587,6 @@ namespace System.Threading.Tasks
}
}
- /// <summary>
- /// Determines whether this is the root task of a self replicating group.
- /// </summary>
- internal bool IsSelfReplicatingRoot
- {
- get
- {
- // Return true if self-replicating bit is set and child replica bit is not set
- return (Options & (TaskCreationOptions)(InternalTaskOptions.SelfReplicating | InternalTaskOptions.ChildReplica))
- == (TaskCreationOptions)InternalTaskOptions.SelfReplicating;
- }
- }
-
- /// <summary>
- /// Determines whether the task is a replica itself.
- /// </summary>
- internal bool IsChildReplica
- {
- get { return (Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) != 0; }
- }
-
- internal int ActiveChildCount
- {
- get
- {
- var props = Volatile.Read(ref m_contingentProperties);
- return props != null ? props.m_completionCountdown - 1 : 0;
- }
- }
/// <summary>
/// The property formerly known as IsFaulted.
@@ -1737,7 +1632,7 @@ namespace System.Threading.Tasks
}
else
{
- return m_contingentProperties?.m_capturedContext ?? ExecutionContext.PreAllocatedDefault;
+ return m_contingentProperties?.m_capturedContext ?? ExecutionContext.Default;
}
}
set
@@ -1747,7 +1642,7 @@ namespace System.Threading.Tasks
{
m_stateFlags |= TASK_STATE_EXECUTIONCONTEXT_IS_NULL;
}
- else if (!value.IsPreAllocatedDefault) // not the default context, then inflate the contingent properties and set it
+ else if (value != ExecutionContext.Default) // not the default context, then inflate the contingent properties and set it
{
EnsureContingentPropertiesInitializedUnsafe().m_capturedContext = value;
}
@@ -1755,32 +1650,6 @@ namespace System.Threading.Tasks
}
}
- /// <summary>
- /// Static helper function to copy specific ExecutionContext
- /// </summary>
- /// <param name="capturedContext">The captured context</param>
- /// <returns>The copied context, null if the capturedContext is null</returns>
- private static ExecutionContext CopyExecutionContext(ExecutionContext capturedContext)
- {
- if (capturedContext == null)
- return null;
- if (capturedContext.IsPreAllocatedDefault)
- return ExecutionContext.PreAllocatedDefault;
-
- return capturedContext.CreateCopy();
- }
-
-
-#if DEBUG
- /// <summary>
- /// Retrieves an identifier for the task.
- /// </summary>
- internal int InternalId
- {
- get { return GetHashCode(); }
- }
-#endif
-
/////////////
// methods
@@ -1920,7 +1789,7 @@ namespace System.Threading.Tasks
catch (ThreadAbortException tae)
{
AddException(tae);
- FinishThreadAbortedTask(true, false);
+ FinishThreadAbortedTask(delegateRan:false);
}
catch (Exception e)
{
@@ -1930,10 +1799,10 @@ namespace System.Threading.Tasks
AddException(tse);
Finish(false);
- // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew()
- // or from the self replicating logic, because in both cases the exception is either propagated outside directly, or added
- // to an enclosing parent. However we won't do this for continuation tasks, because in that case we internally eat the exception
- // and therefore we need to make sure the user does later observe it explicitly or see it on the finalizer.
+ // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew(),
+ // because the exception is either propagated outside directly, or added to an enclosing parent. However we won't do this for
+ // continuation tasks, because in that case we internally eat the exception and therefore we need to make sure the user does
+ // later observe it explicitly or see it on the finalizer.
if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
{
@@ -2192,11 +2061,9 @@ namespace System.Threading.Tasks
var props = Volatile.Read(ref m_contingentProperties);
if (props == null || // no contingent properties means no children, so it's safe to complete ourselves
- (props.m_completionCountdown == 1 && !IsSelfReplicatingRoot) ||
+ (props.m_completionCountdown == 1) ||
// Count of 1 => either all children finished, or there were none. Safe to complete ourselves
// without paying the price of an Interlocked.Decrement.
- // However we need to exclude self replicating root tasks from this optimization, because
- // they can have children joining in, or finishing even after the root task delegate is done.
Interlocked.Decrement(ref props.m_completionCountdown) == 0) // Reaching this sub clause means there may be remaining active children,
// and we could be racing with one of them to call FinishStageTwo().
// So whoever does the final Interlocked.Dec is responsible to finish.
@@ -2424,19 +2291,13 @@ namespace System.Threading.Tasks
/// This makes a note in the state flags so that we avoid any costly synchronous operations in the finish codepath
/// such as inlined continuations
/// </summary>
- /// <param name="bTAEAddedToExceptionHolder">
- /// Indicates whether the ThreadAbortException was added to this task's exception holder.
- /// This should always be true except for the case of non-root self replicating task copies.
- /// </param>
/// <param name="delegateRan">Whether the delegate was executed.</param>
- internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan)
+ internal void FinishThreadAbortedTask(bool delegateRan)
{
- Debug.Assert(!bTAEAddedToExceptionHolder || m_contingentProperties?.m_exceptionsHolder != null,
- "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");
+ Debug.Assert(m_contingentProperties?.m_exceptionsHolder != null,
+ "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");
- // this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task.
- if (bTAEAddedToExceptionHolder)
- m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
+ m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
// If this method has already been called for this task, or if this task has already completed, then
// return before actually calling Finish().
@@ -2447,220 +2308,33 @@ namespace System.Threading.Tasks
}
Finish(delegateRan);
-
}
/// <summary>
- /// Executes the task. This method will only be called once, and handles bookeeping associated with
- /// self-replicating tasks, in addition to performing necessary exception marshaling.
+ /// Executes the task. This method will only be called once, and handles any necessary exception marshaling.
/// </summary>
private void Execute()
{
- if (IsSelfReplicatingRoot)
+ try
{
- ExecuteSelfReplicating(this);
+ InnerInvoke();
}
- else
+ catch (ThreadAbortException tae)
{
- try
- {
- InnerInvoke();
- }
- catch (ThreadAbortException tae)
- {
- // Don't record the TAE or call FinishThreadAbortedTask for a child replica task --
- // it's already been done downstream.
- if (!IsChildReplica)
- {
- // Record this exception in the task's exception list
- HandleException(tae);
+ // Record this exception in the task's exception list
+ HandleException(tae);
- // This is a ThreadAbortException and it will be rethrown from this catch clause, causing us to
- // skip the regular Finish codepath. In order not to leave the task unfinished, we now call
- // FinishThreadAbortedTask here.
- FinishThreadAbortedTask(true, true);
- }
- }
- catch (Exception exn)
- {
- // Record this exception in the task's exception list
- HandleException(exn);
- }
+ // This is a ThreadAbortException and it will be rethrown from this catch clause, causing us to
+ // skip the regular Finish codepath. In order not to leave the task unfinished, we now call
+ // FinishThreadAbortedTask here.
+ FinishThreadAbortedTask(delegateRan: true);
}
- }
-
- // Allows (internal) deriving classes to support limited replication.
- // (By default, replication is basically unlimited).
- internal virtual bool ShouldReplicate()
- {
- return true;
- }
-
- // Allows (internal) deriving classes to instantiate the task replica as a Task super class of their choice
- // (By default, we create a regular Task instance)
- internal virtual Task CreateReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
- TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
- {
- return new Task(taskReplicaDelegate, stateObject, parentTask, default(CancellationToken),
- creationOptionsForReplica, internalOptionsForReplica, parentTask.ExecutingTaskScheduler);
- }
-
- // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
- internal virtual Object SavedStateForNextReplica
- {
- get { return null; }
-
- set { /*do nothing*/ }
- }
-
- // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
- internal virtual Object SavedStateFromPreviousReplica
- {
- get { return null; }
-
- set { /*do nothing*/ }
- }
-
- // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
- // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one
- internal virtual Task HandedOverChildReplica
- {
- get { return null; }
-
- set { /* do nothing*/ }
- }
-
- private static void ExecuteSelfReplicating(Task root)
- {
- TaskCreationOptions creationOptionsForReplicas = root.CreationOptions | TaskCreationOptions.AttachedToParent;
- InternalTaskOptions internalOptionsForReplicas =
- InternalTaskOptions.ChildReplica | // child replica flag disables self replication for the replicas themselves.
- InternalTaskOptions.SelfReplicating | // we still want to identify this as part of a self replicating group
- InternalTaskOptions.QueuedByRuntime; // we queue and cancel these tasks internally, so don't allow CT registration to take place
-
-
- // Important Note: The child replicas we launch from here will be attached the root replica (by virtue of the root.CreateReplicaTask call)
- // because we need the root task to receive all their exceptions, and to block until all of them return
-
-
- // This variable is captured in a closure and shared among all replicas.
- bool replicasAreQuitting = false;
-
- // Set up a delegate that will form the body of the root and all recursively created replicas.
- Action<object> taskReplicaDelegate = null;
- taskReplicaDelegate = delegate
+ catch (Exception exn)
{
- Task currentTask = Task.InternalCurrent;
-
-
- // Check if a child task has been handed over by a prematurely quiting replica that we might be a replacement for.
- Task childTask = currentTask.HandedOverChildReplica;
-
- if (childTask == null)
- {
- // Apparently we are not a replacement task. This means we need to queue up a child task for replication to progress
-
- // Down-counts a counter in the root task.
- if (!root.ShouldReplicate()) return;
-
- // If any of the replicas have quit, we will do so ourselves.
- if (Volatile.Read(ref replicasAreQuitting))
- {
- return;
- }
-
- // Propagate a copy of the context from the root task. It may be null if flow was suppressed.
- ExecutionContext creatorContext = root.CapturedContext;
-
-
- childTask = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
- creationOptionsForReplicas, internalOptionsForReplicas);
-
- childTask.CapturedContext = CopyExecutionContext(creatorContext);
-
- childTask.ScheduleAndStart(false);
- }
-
-
-
- // Finally invoke the meat of the task.
- // Note that we are directly calling root.InnerInvoke() even though we are currently be in the action delegate of a child replica
- // This is because the actual work was passed down in that delegate, and the action delegate of the child replica simply contains this
- // replication control logic.
- try
- {
- // passing in currentTask only so that the parallel debugger can find it
- root.InnerInvokeWithArg(currentTask);
- }
- catch (Exception exn)
- {
- // Record this exception in the root task's exception list
- root.HandleException(exn);
-
- if (exn is ThreadAbortException)
- {
- // If this is a ThreadAbortException it will escape this catch clause, causing us to skip the regular Finish codepath
- // In order not to leave the task unfinished, we now call FinishThreadAbortedTask here
- currentTask.FinishThreadAbortedTask(false, true);
- }
- }
-
- Object savedState = currentTask.SavedStateForNextReplica;
-
- // check for premature exit
- if (savedState != null)
- {
- // the replica decided to exit early
- // we need to queue up a replacement, attach the saved state, and yield the thread right away
-
- Task replacementReplica = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
- creationOptionsForReplicas, internalOptionsForReplicas);
-
- // Propagate a copy of the context from the root task to the replacement task
- ExecutionContext creatorContext = root.CapturedContext;
- replacementReplica.CapturedContext = CopyExecutionContext(creatorContext);
-
- replacementReplica.HandedOverChildReplica = childTask;
- replacementReplica.SavedStateFromPreviousReplica = savedState;
-
- replacementReplica.ScheduleAndStart(false);
- }
- else
- {
- // The replica finished normally, which means it can't find more work to grab.
- // Time to mark replicas quitting
-
- replicasAreQuitting = true;
-
- // InternalCancel() could conceivably throw in the underlying scheduler's TryDequeue() method.
- // If it does, then make sure that we record it.
- try
- {
- childTask.InternalCancel(true);
- }
- catch (Exception e)
- {
- // Apparently TryDequeue threw an exception. Before propagating that exception, InternalCancel should have
- // attempted an atomic state transition and a call to CancellationCleanupLogic() on this task. So we know
- // the task was properly cleaned up if it was possible.
- //
- // Now all we need to do is to Record the exception in the root task.
-
- root.HandleException(e);
- }
-
- // No specific action needed if the child could not be canceled
- // because we attached it to the root task, which should therefore be receiving any exceptions from the child,
- // and root.wait will not return before this child finishes anyway.
-
- }
- };
-
- //
- // Now we execute as the root task
- //
- taskReplicaDelegate(null);
+ // Record this exception in the task's exception list
+ HandleException(exn);
+ }
}
/// <summary>
@@ -2683,7 +2357,7 @@ namespace System.Threading.Tasks
if (!IsCompleted)
{
HandleException(tae);
- FinishThreadAbortedTask(true, false);
+ FinishThreadAbortedTask(delegateRan:false);
}
}
@@ -2693,10 +2367,10 @@ namespace System.Threading.Tasks
///
/// </summary>
/// <param name="bPreventDoubleExecution"> Performs atomic updates to prevent double execution. Should only be set to true
- /// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. </param>
+ /// in codepaths servicing user provided TaskSchedulers. The ThreadPool scheduler doesn't need this. </param>
internal bool ExecuteEntry(bool bPreventDoubleExecution)
{
- if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0))
+ if (bPreventDoubleExecution)
{
int previousState = 0;
@@ -2772,18 +2446,10 @@ namespace System.Threading.Tasks
}
else
{
- if (IsSelfReplicatingRoot || IsChildReplica)
- {
- CapturedContext = CopyExecutionContext(ec);
- }
-
// Run the task. We need a simple shim that converts the
// object back into a Task object, so that we can Execute it.
- // Lazily initialize the callback delegate; benign race condition
- var callback = s_ecCallback;
- if (callback == null) s_ecCallback = callback = new ContextCallback(ExecutionContextCallback);
- ExecutionContext.Run(ec, callback, this, true);
+ ExecutionContext.Run(ec, s_ecCallback, this);
}
if (AsyncCausalityTracer.LoggingOn)
@@ -2810,16 +2476,7 @@ namespace System.Threading.Tasks
}
}
- // Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical
- private static ContextCallback s_ecCallback;
-
- private static void ExecutionContextCallback(object obj)
- {
- Task task = obj as Task;
- Debug.Assert(task != null, "expected a task object");
- task.Execute();
- }
-
+ private static readonly ContextCallback s_ecCallback = obj => ((Task)obj).Execute();
/// <summary>
/// The actual code which invokes the body of the task. This can be overriden in derived types.
@@ -2844,21 +2501,6 @@ namespace System.Threading.Tasks
}
/// <summary>
- /// Alternate InnerInvoke prototype to be called from ExecuteSelfReplicating() so that
- /// the Parallel Debugger can discover the actual task being invoked.
- /// Details: Here, InnerInvoke is actually being called on the rootTask object while we are actually executing the
- /// childTask. And the debugger needs to discover the childTask, so we pass that down as an argument.
- /// The NoOptimization and NoInlining flags ensure that the childTask pointer is retained, and that this
- /// function appears on the callstack.
- /// </summary>
- /// <param name="childTask"></param>
- [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
- internal void InnerInvokeWithArg(Task childTask)
- {
- InnerInvoke();
- }
-
- /// <summary>
/// Performs whatever handling is necessary for an unhandled exception. Normally
/// this just entails adding the exception to the holder object.
/// </summary>
@@ -2917,10 +2559,9 @@ namespace System.Threading.Tasks
/// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
/// </param>
/// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
- /// <param name="stackMark">A stack crawl mark tied to execution context.</param>
/// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
internal void SetContinuationForAwait(
- Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext, ref StackCrawlMark stackMark)
+ Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext)
{
Contract.Requires(continuationAction != null);
@@ -2941,7 +2582,7 @@ namespace System.Threading.Tasks
var syncCtx = SynchronizationContext.CurrentNoFlow;
if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
{
- tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, continuationAction, flowExecutionContext, ref stackMark);
+ tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, continuationAction, flowExecutionContext);
}
else
{
@@ -2950,7 +2591,7 @@ namespace System.Threading.Tasks
var scheduler = TaskScheduler.InternalCurrent;
if (scheduler != null && scheduler != TaskScheduler.Default)
{
- tc = new TaskSchedulerAwaitTaskContinuation(scheduler, continuationAction, flowExecutionContext, ref stackMark);
+ tc = new TaskSchedulerAwaitTaskContinuation(scheduler, continuationAction, flowExecutionContext);
}
}
}
@@ -2962,7 +2603,7 @@ namespace System.Threading.Tasks
// ExecutionContext, we need to capture it and wrap it in an AwaitTaskContinuation.
// Otherwise, we're targeting the default scheduler and we don't need to flow ExecutionContext, so
// we don't actually need a continuation object. We can just store/queue the action itself.
- tc = new AwaitTaskContinuation(continuationAction, flowExecutionContext: true, stackMark: ref stackMark);
+ tc = new AwaitTaskContinuation(continuationAction, flowExecutionContext: true);
}
// Now register the continuation, and if we couldn't register it because the task is already completing,
@@ -3190,7 +2831,7 @@ namespace System.Threading.Tasks
Task currentTask = Task.InternalCurrent;
etwLog.TaskWaitBegin(
(currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
- this.Id, TplEtwProvider.TaskWaitBehavior.Synchronous, 0, System.Threading.Thread.GetDomainID());
+ this.Id, TplEtwProvider.TaskWaitBehavior.Synchronous, 0);
}
bool returnValue = IsCompleted;
@@ -3377,7 +3018,7 @@ namespace System.Threading.Tasks
}
}
- bool bRequiresAtomicStartTransition = (ts != null && ts.RequiresAtomicStartTransition) || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0);
+ bool bRequiresAtomicStartTransition = ts != null && ts.RequiresAtomicStartTransition;
if (!bPopSucceeded && bCancelNonExecutingOnly && bRequiresAtomicStartTransition)
{
@@ -3715,11 +3356,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task> continuationAction)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -3742,11 +3381,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
@@ -3771,11 +3408,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -3806,11 +3441,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -3851,17 +3484,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
private Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler,
- CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null action
if (continuationAction == null)
@@ -3882,8 +3513,7 @@ namespace System.Threading.Tasks
Task continuationTask = new ContinuationTaskFromTask(
this, continuationAction, null,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -3913,11 +3543,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task, Object> continuationAction, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -3941,11 +3569,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
@@ -3971,11 +3597,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -4007,11 +3631,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -4053,17 +3675,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
private Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler,
- CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null action
if (continuationAction == null)
@@ -4084,8 +3704,7 @@ namespace System.Threading.Tasks
Task continuationTask = new ContinuationTaskFromTask(
this, continuationAction, state,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -4118,12 +3737,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken),
- TaskContinuationOptions.None, ref stackMark);
+ TaskContinuationOptions.None);
}
@@ -4150,11 +3767,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
@@ -4182,11 +3797,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -4220,11 +3833,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -4268,17 +3879,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
private Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler,
- CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null function
if (continuationFunction == null)
@@ -4299,8 +3908,7 @@ namespace System.Threading.Tasks
Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
this, continuationFunction, null,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -4333,12 +3941,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken),
- TaskContinuationOptions.None, ref stackMark);
+ TaskContinuationOptions.None);
}
@@ -4366,11 +3972,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
@@ -4399,11 +4003,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -4438,11 +4040,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -4487,17 +4087,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark parameter.
private Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler,
- CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
// Throw on continuation with null function
if (continuationFunction == null)
@@ -4518,8 +4116,7 @@ namespace System.Threading.Tasks
Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
this, continuationFunction, state,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -5207,49 +4804,6 @@ namespace System.Threading.Tasks
}
/// <summary>
- /// Internal WaitAll implementation which is meant to be used with small number of tasks,
- /// optimized for Parallel.Invoke and other structured primitives.
- /// </summary>
- internal static void FastWaitAll(Task[] tasks)
- {
- Contract.Requires(tasks != null);
-
- List<Exception> exceptions = null;
-
- // Collects incomplete tasks in "waitedOnTaskList" and their cooperative events in "cooperativeEventList"
- for (int i = tasks.Length - 1; i >= 0; i--)
- {
- if (!tasks[i].IsCompleted)
- {
- // Just attempting to inline here... result doesn't matter.
- // We'll do a second pass to do actual wait on each task, and to aggregate their exceptions.
- // If the task is inlined here, it will register as IsCompleted in the second pass
- // and will just give us the exception.
- tasks[i].WrappedTryRunInline();
- }
- }
-
- // Wait on the tasks.
- for (int i = tasks.Length - 1; i >= 0; i--)
- {
- var task = tasks[i];
- task.SpinThenBlockingWait(Timeout.Infinite, default(CancellationToken));
- AddExceptionsForCompletedTask(ref exceptions, task);
-
- // Note that unlike other wait code paths, we do not check
- // task.NotifyDebuggerOfWaitCompletionIfNecessary() here, because this method is currently
- // only used from contexts where the tasks couldn't have that bit set, namely
- // Parallel.Invoke. If that ever changes, such checks should be added here.
- }
-
- // If one or more threw exceptions, aggregate them.
- if (exceptions != null)
- {
- ThrowHelper.ThrowAggregateException(exceptions);
- }
- }
-
- /// <summary>
/// This internal function is only meant to be called by WaitAll()
/// If the completed task is canceled or it has other exceptions, here we will add those
/// into the passed in exception list (which will be lazily initialized here).
@@ -5582,12 +5136,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="action"/> parameter was null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public static Task Run(Action action)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task.InternalStartNew(null, action, null, default(CancellationToken), TaskScheduler.Default,
- TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark);
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None);
}
/// <summary>
@@ -5602,12 +5154,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">
/// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public static Task Run(Action action, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task.InternalStartNew(null, action, null, cancellationToken, TaskScheduler.Default,
- TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark);
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None);
}
/// <summary>
@@ -5618,12 +5168,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="function"/> parameter was null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public static Task<TResult> Run<TResult>(Func<TResult> function)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task<TResult>.StartNew(null, function, default(CancellationToken),
- TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default, ref stackMark);
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default);
}
/// <summary>
@@ -5638,12 +5186,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">
/// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task<TResult>.StartNew(null, function, cancellationToken,
- TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default, ref stackMark);
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default);
}
/// <summary>
@@ -6693,102 +6239,6 @@ namespace System.Threading.Tasks
public TaskStatus Status { get { return m_task.Status; } }
}
- // Special purpose derivation of Task that supports limited replication through
- // overriding the ShouldReplicate() method. This is used by the Parallel.For/ForEach
- // methods.
- internal class ParallelForReplicatingTask : Task
- {
- // Member variables
- private int m_replicationDownCount; // downcounter to control replication
-
- //
- // Constructors
- //
-
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
- internal ParallelForReplicatingTask(
- ParallelOptions parallelOptions, Action action, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions)
- : base(action, null, Task.InternalCurrent, default(CancellationToken), creationOptions, internalOptions | InternalTaskOptions.SelfReplicating, null)
- {
- // Compute the down count based on scheduler/DOP info in parallelOptions.
- m_replicationDownCount = parallelOptions.EffectiveMaxConcurrencyLevel;
-
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
- }
-
-
- // Controls degree of replication. If downcounter is initialized to -1, then
- // replication will be allowed to "run wild". Otherwise, this method decrements
- // the downcounter each time it is called, calling false when it is called with
- // a zero downcounter. This method returning false effectively ends the replication
- // of the associated ParallelForReplicatingTask.
- internal override bool ShouldReplicate()
- {
- if (m_replicationDownCount == -1) return true; // "run wild"
-
- if (m_replicationDownCount > 0) // Decrement and return true if not called with 0 downcount
- {
- m_replicationDownCount--;
- return true;
- }
-
- return false; // We're done replicating
- }
-
- internal override Task CreateReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
- TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
- {
- return new ParallelForReplicaTask(taskReplicaDelegate, stateObject, parentTask, taskScheduler,
- creationOptionsForReplica, internalOptionsForReplica);
- }
-
-
- }
-
- internal class ParallelForReplicaTask : Task
- {
- internal object m_stateForNextReplica; // some replicas may quit prematurely, in which case they will use this variable
- // to save state they want to be picked up by the next replica queued to the same thread
-
- internal object m_stateFromPreviousReplica; // some replicas may quit prematurely, in which case they will use this variable
- // to save state they want to be picked up by the next replica queued to the same thread
-
- internal Task m_handedOverChildReplica; // some replicas may quit prematurely, in which case they will use this variable
- // to hand over the child replica they had queued to the next task that will replace them
-
- internal ParallelForReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
- TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) :
- base(taskReplicaDelegate, stateObject, parentTask, default(CancellationToken), creationOptionsForReplica, internalOptionsForReplica, taskScheduler)
- {
- }
-
- // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
- internal override Object SavedStateForNextReplica
- {
- get { return m_stateForNextReplica; }
-
- set { m_stateForNextReplica = value; }
- }
-
- // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
- internal override Object SavedStateFromPreviousReplica
- {
- get { return m_stateFromPreviousReplica; }
-
- set { m_stateFromPreviousReplica = value; }
- }
-
- // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
- // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one
- internal override Task HandedOverChildReplica
- {
- get { return m_handedOverChildReplica; }
-
- set { m_handedOverChildReplica = value; }
- }
- }
-
/// <summary>
/// Specifies flags that control optional behavior for the creation and execution of tasks.
/// </summary>
@@ -6856,10 +6306,8 @@ namespace System.Threading.Tasks
/// <summary>Used to filter out internal vs. public task creation options.</summary>
InternalOptionsMask = 0x0000FF00,
- ChildReplica = 0x0100,
ContinuationTask = 0x0200,
PromiseTask = 0x0400,
- SelfReplicating = 0x0800,
/// <summary>
/// Store the presence of TaskContinuationOptions.LazyCancellation, since it does not directly
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs b/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs
index 320f704..bf9f9cb 100644
--- a/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs
@@ -17,7 +17,6 @@ using System.Diagnostics.Contracts;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
-using System.Security.Permissions;
using System.Threading;
// Disable the "reference to volatile field not treated as volatile" error.
@@ -203,22 +202,6 @@ namespace System.Threading.Tasks
return rval;
}
- /// <summary>Attempts to transition the underlying task to the faulted state.</summary>
- /// <param name="exceptions">The collection of exception dispatch infos to bind to this task.</param>
- /// <returns>True if the operation was successful; otherwise, false.</returns>
- /// <remarks>Unlike the public methods, this method doesn't currently validate that its arguments are correct.</remarks>
- internal bool TrySetException(IEnumerable<ExceptionDispatchInfo> exceptions)
- {
- Debug.Assert(exceptions != null);
-#if DEBUG
- foreach(var edi in exceptions) Debug.Assert(edi != null, "Contents must be non-null");
-#endif
-
- bool rval = m_task.TrySetException(exceptions);
- if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
- return rval;
- }
-
/// <summary>
/// Transitions the underlying
/// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs b/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs
index 70b9418d..3c6ccd8 100644
--- a/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs
@@ -29,13 +29,12 @@ namespace System.Threading.Tasks
private Task m_antecedent;
public ContinuationTaskFromTask(
- Task antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ Task antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
{
Contract.Requires(action is Action<Task> || action is Action<Task, object>,
"Invalid delegate type in ContinuationTaskFromTask");
m_antecedent = antecedent;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -77,13 +76,12 @@ namespace System.Threading.Tasks
private Task m_antecedent;
public ContinuationResultTaskFromTask(
- Task antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ Task antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
{
Contract.Requires(function is Func<Task, TResult> || function is Func<Task, object, TResult>,
"Invalid delegate type in ContinuationResultTaskFromTask");
m_antecedent = antecedent;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -125,13 +123,12 @@ namespace System.Threading.Tasks
private Task<TAntecedentResult> m_antecedent;
public ContinuationTaskFromResultTask(
- Task<TAntecedentResult> antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ Task<TAntecedentResult> antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
{
Contract.Requires(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object>,
"Invalid delegate type in ContinuationTaskFromResultTask");
m_antecedent = antecedent;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -173,13 +170,12 @@ namespace System.Threading.Tasks
private Task<TAntecedentResult> m_antecedent;
public ContinuationResultTaskFromResultTask(
- Task<TAntecedentResult> antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ Task<TAntecedentResult> antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) :
base(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
{
Contract.Requires(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object, TResult>,
"Invalid delegate type in ContinuationResultTaskFromResultTask");
m_antecedent = antecedent;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -392,10 +388,9 @@ namespace System.Threading.Tasks
/// <param name="context">The synchronization context with which to invoke the action. Must not be null.</param>
/// <param name="action">The action to invoke. Must not be null.</param>
/// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
- /// <param name="stackMark">The captured stack mark.</param>
internal SynchronizationContextAwaitTaskContinuation(
- SynchronizationContext context, Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) :
- base(action, flowExecutionContext, ref stackMark)
+ SynchronizationContext context, Action action, bool flowExecutionContext) :
+ base(action, flowExecutionContext)
{
Debug.Assert(context != null);
m_syncContext = context;
@@ -479,10 +474,9 @@ namespace System.Threading.Tasks
/// <param name="scheduler">The task scheduler with which to invoke the action. Must not be null.</param>
/// <param name="action">The action to invoke. Must not be null.</param>
/// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
- /// <param name="stackMark">The captured stack mark.</param>
internal TaskSchedulerAwaitTaskContinuation(
- TaskScheduler scheduler, Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) :
- base(action, flowExecutionContext, ref stackMark)
+ TaskScheduler scheduler, Action action, bool flowExecutionContext) :
+ base(action, flowExecutionContext)
{
Debug.Assert(scheduler != null);
m_scheduler = scheduler;
@@ -543,29 +537,13 @@ namespace System.Threading.Tasks
/// <summary>Initializes the continuation.</summary>
/// <param name="action">The action to invoke. Must not be null.</param>
/// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
- /// <param name="stackMark">The captured stack mark with which to construct an ExecutionContext.</param>
- internal AwaitTaskContinuation(Action action, bool flowExecutionContext, ref StackCrawlMark stackMark)
- {
- Contract.Requires(action != null);
- m_action = action;
- if (flowExecutionContext)
- {
- m_capturedContext = ExecutionContext.Capture(
- ref stackMark,
- ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
- }
- }
-
- /// <summary>Initializes the continuation.</summary>
- /// <param name="action">The action to invoke. Must not be null.</param>
- /// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
internal AwaitTaskContinuation(Action action, bool flowExecutionContext)
{
Contract.Requires(action != null);
m_action = action;
if (flowExecutionContext)
{
- m_capturedContext = ExecutionContext.FastCapture();
+ m_capturedContext = ExecutionContext.Capture();
}
}
@@ -670,11 +648,7 @@ namespace System.Threading.Tasks
// If there is an execution context, get the cached delegate and run the action under the context.
else
{
- try
- {
- ExecutionContext.Run(m_capturedContext, GetInvokeActionCallback(), m_action, true);
- }
- finally { m_capturedContext.Dispose(); }
+ ExecutionContext.Run(m_capturedContext, GetInvokeActionCallback(), m_action);
}
}
finally
@@ -689,8 +663,7 @@ namespace System.Threading.Tasks
void IThreadPoolWorkItem.ExecuteWorkItem()
{
// inline the fast path
- if (m_capturedContext == null && !TplEtwProvider.Log.IsEnabled()
- )
+ if (m_capturedContext == null && !TplEtwProvider.Log.IsEnabled())
{
m_action();
}
@@ -739,7 +712,7 @@ namespace System.Threading.Tasks
// If there's no captured context, just run the callback directly.
if (m_capturedContext == null) callback(state);
// Otherwise, use the captured context to do so.
- else ExecutionContext.Run(m_capturedContext, callback, state, true);
+ else ExecutionContext.Run(m_capturedContext, callback, state);
}
catch (Exception exc) // we explicitly do not request handling of dangerous exceptions like AVs
{
@@ -749,9 +722,6 @@ namespace System.Threading.Tasks
{
// Restore the current task information
if (prevCurrentTask != null) currentTask = prevCurrentTask;
-
- // Clean up after the execution context, which is only usable once.
- if (m_capturedContext != null) m_capturedContext.Dispose();
}
}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs b/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs
index 45817da..ee1112a 100644
--- a/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs
@@ -149,23 +149,6 @@ namespace System.Threading.Tasks
/// Add an exception to the holder. This will ensure the holder is
/// in the proper state (handled/unhandled) depending on the list's contents.
/// </summary>
- /// <param name="exceptionObject">
- /// An exception object (either an Exception, an ExceptionDispatchInfo,
- /// an IEnumerable{Exception}, or an IEnumerable{ExceptionDispatchInfo})
- /// to add to the list.
- /// </param>
- /// <remarks>
- /// Must be called under lock.
- /// </remarks>
- internal void Add(object exceptionObject)
- {
- Add(exceptionObject, representsCancellation: false);
- }
-
- /// <summary>
- /// Add an exception to the holder. This will ensure the holder is
- /// in the proper state (handled/unhandled) depending on the list's contents.
- /// </summary>
/// <param name="representsCancellation">
/// Whether the exception represents a cancellation request (true) or a fault (false).
/// </param>
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs
index aa4c2df..89ba298 100644
--- a/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs
@@ -15,7 +15,6 @@
using System;
using System.Collections.Generic;
using System.Security;
-using System.Security.Permissions;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Diagnostics;
@@ -225,7 +224,7 @@ namespace System.Threading.Tasks
TaskCreationOptions.PreferFairness |
TaskCreationOptions.RunContinuationsAsynchronously)) != 0)
{
- throw new ArgumentOutOfRangeException(nameof(creationOptions));
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions);
}
Contract.EndContractBlock();
}
@@ -293,13 +292,11 @@ namespace System.Threading.Tasks
/// unless creation and scheduling must be separated, StartNew is the recommended
/// approach for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action action)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask),
- m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None);
}
/// <summary>
@@ -320,13 +317,11 @@ namespace System.Threading.Tasks
/// unless creation and scheduling must be separated, StartNew is the recommended
/// approach for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action action, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, cancellationToken, GetDefaultScheduler(currTask),
- m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None);
}
/// <summary>
@@ -350,13 +345,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action action, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask), creationOptions,
- InternalTaskOptions.None, ref stackMark);
+ InternalTaskOptions.None);
}
/// <summary>
@@ -391,22 +384,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task.InternalStartNew(
Task.InternalCurrentIfAttached(creationOptions), action, null, cancellationToken, scheduler, creationOptions,
- InternalTaskOptions.None, ref stackMark);
- }
-
- // Internal version includes InternalTaskOptions for Parallel.Invoke() support.
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
- internal Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
- {
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return Task.InternalStartNew(
- Task.InternalCurrentIfAttached(creationOptions), action, null, cancellationToken, scheduler, creationOptions, internalOptions, ref stackMark);
+ InternalTaskOptions.None);
}
@@ -427,13 +409,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action<Object> action, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
- m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None);
}
@@ -458,13 +438,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask),
- m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None);
}
/// <summary>
@@ -490,13 +468,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action<Object> action, Object state, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
- creationOptions, InternalTaskOptions.None, ref stackMark);
+ creationOptions, InternalTaskOptions.None);
}
/// <summary>
@@ -533,14 +509,12 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task.InternalStartNew(
Task.InternalCurrentIfAttached(creationOptions), action, state, cancellationToken, scheduler,
- creationOptions, InternalTaskOptions.None, ref stackMark);
+ creationOptions, InternalTaskOptions.None);
}
/// <summary>
@@ -562,13 +536,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<TResult> function)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -595,13 +567,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, cancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -629,13 +599,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<TResult> function, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
- creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -674,13 +642,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task<TResult>.StartNew(
Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken,
- creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ creationOptions, InternalTaskOptions.None, scheduler);
}
/// <summary>
@@ -704,13 +670,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
@@ -739,13 +703,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
- m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -775,13 +737,11 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
Task currTask = Task.InternalCurrent;
return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
- creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask));
}
/// <summary>
@@ -822,14 +782,12 @@ namespace System.Threading.Tasks
/// However, unless creation and scheduling must be separated, StartNew is the recommended approach
/// for both simplicity and performance.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
return Task<TResult>.StartNew(
Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
- creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ creationOptions, InternalTaskOptions.None, scheduler);
}
//
@@ -850,13 +808,11 @@ namespace System.Threading.Tasks
/// <paramref name="endMethod"/> argument is null.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous
/// operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task FromAsync(
IAsyncResult asyncResult,
Action<IAsyncResult> endMethod)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return FromAsync(asyncResult, endMethod, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
+ return FromAsync(asyncResult, endMethod, m_defaultCreationOptions, DefaultScheduler);
}
/// <summary>
@@ -878,14 +834,12 @@ namespace System.Threading.Tasks
/// value.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous
/// operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task FromAsync(
IAsyncResult asyncResult,
Action<IAsyncResult> endMethod,
TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return FromAsync(asyncResult, endMethod, creationOptions, DefaultScheduler, ref stackMark);
+ return FromAsync(asyncResult, endMethod, creationOptions, DefaultScheduler);
}
/// <summary>
@@ -911,26 +865,13 @@ namespace System.Threading.Tasks
/// value.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous
/// operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task FromAsync(
IAsyncResult asyncResult,
Action<IAsyncResult> endMethod,
TaskCreationOptions creationOptions,
TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return FromAsync(asyncResult, endMethod, creationOptions, scheduler, ref stackMark);
- }
-
- // private version that supports StackCrawlMark.
- private Task FromAsync(
- IAsyncResult asyncResult,
- Action<IAsyncResult> endMethod,
- TaskCreationOptions creationOptions,
- TaskScheduler scheduler,
- ref StackCrawlMark stackMark)
- {
- return TaskFactory<VoidTaskResult>.FromAsyncImpl(asyncResult, null, endMethod, creationOptions, scheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.FromAsyncImpl(asyncResult, null, endMethod, creationOptions, scheduler);
}
/// <summary>
@@ -1228,12 +1169,10 @@ namespace System.Threading.Tasks
/// <paramref name="endMethod"/> argument is null.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
/// asynchronous operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> FromAsync<TResult>(
IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler);
}
/// <summary>
@@ -1258,12 +1197,10 @@ namespace System.Threading.Tasks
/// value.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
/// asynchronous operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> FromAsync<TResult>(
IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler);
}
/// <summary>
@@ -1292,12 +1229,10 @@ namespace System.Threading.Tasks
/// value.</exception>
/// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
/// asynchronous operation.</returns>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> FromAsync<TResult>(
IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark);
+ return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler);
}
/// <summary>
@@ -1606,7 +1541,7 @@ namespace System.Threading.Tasks
TaskCreationOptions.PreferFairness |
TaskCreationOptions.LongRunning)) != 0)
{
- throw new ArgumentOutOfRangeException(nameof(creationOptions));
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions);
}
}
@@ -1798,14 +1733,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
@@ -1830,14 +1763,12 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1867,14 +1798,12 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, TaskContinuationOptions continuationOptions)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -1914,15 +1843,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler);
}
/// <summary>
@@ -1942,14 +1869,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
@@ -1975,15 +1900,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
CancellationToken cancellationToken)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2014,15 +1937,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
TaskContinuationOptions continuationOptions)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2063,15 +1984,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler);
}
/// <summary>
@@ -2094,14 +2013,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
@@ -2130,14 +2047,12 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2171,14 +2086,12 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2222,15 +2135,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
@@ -2255,14 +2166,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2291,15 +2200,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
CancellationToken cancellationToken)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2334,15 +2241,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2387,15 +2292,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAll.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
//
@@ -2505,7 +2408,23 @@ namespace System.Threading.Tasks
checkArgsOnly = true;
}
// Otherwise, add the completion action and keep going.
- else task.AddCompletionAction(promise);
+ else
+ {
+ task.AddCompletionAction(promise);
+ if (promise.IsCompleted)
+ {
+ // One of the previous tasks that already had its continuation registered may have
+ // raced to complete with our adding the continuation to this task. The completion
+ // routine would have gone through and removed the continuation from all of the tasks
+ // with which it was already registered, but if the race causes this continuation to
+ // be added after that, it'll never be removed. As such, after adding the continuation,
+ // we check to see whether the promise has already completed, and if it has, we try to
+ // manually remove the continuation from this task. If it was already removed, it'll be
+ // a nop, and if we race to remove it, the synchronization in RemoveContinuation will
+ // keep things consistent.
+ task.RemoveContinuation(promise);
+ }
+ }
}
return promise;
@@ -2528,14 +2447,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2559,14 +2476,12 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2596,14 +2511,12 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2643,15 +2556,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler);
}
@@ -2675,14 +2586,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2710,14 +2619,12 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2751,14 +2658,12 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null,continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null,continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2802,15 +2707,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
/// <summary>
@@ -2834,12 +2737,10 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
- return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2868,15 +2769,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
CancellationToken cancellationToken)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2911,15 +2810,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -2964,15 +2861,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationFunction == null) throw new ArgumentNullException(nameof(continuationFunction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler);
}
@@ -2993,14 +2888,12 @@ namespace System.Threading.Tasks
/// <paramref name="tasks"/> array contains a null value.</exception>
/// <exception cref="T:System.ArgumentException">The exception that is thrown when the
/// <paramref name="tasks"/> array is empty.</exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -3025,15 +2918,13 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
CancellationToken cancellationToken)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler);
}
/// <summary>
@@ -3064,15 +2955,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
TaskContinuationOptions continuationOptions)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler);
}
/// <summary>
@@ -3113,15 +3002,13 @@ namespace System.Threading.Tasks
/// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
/// will be executed, are illegal with ContinueWhenAny.
/// </remarks>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
if (continuationAction == null) throw new ArgumentNullException(nameof(continuationAction));
Contract.EndContractBlock();
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler);
}
// Check task array and return a defensive copy.
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs b/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs
index fad3fc0..d68c3fe 100644
--- a/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs
@@ -16,7 +16,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Security;
-using System.Security.Permissions;
using System.Collections.Concurrent;
using System.Diagnostics.Contracts;
using System.Diagnostics;
diff --git a/src/mscorlib/src/System/Threading/Tasks/future.cs b/src/mscorlib/src/System/Threading/Tasks/future.cs
index 0c3fec8..15136f1 100644
--- a/src/mscorlib/src/System/Threading/Tasks/future.cs
+++ b/src/mscorlib/src/System/Threading/Tasks/future.cs
@@ -16,7 +16,6 @@ using System.Runtime;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Security;
-using System.Security.Permissions;
using System.Threading;
using System.Diagnostics;
using System.Diagnostics.Contracts;
@@ -128,13 +127,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentException">
/// The <paramref name="function"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<TResult> function)
: this(function, null, default(CancellationToken),
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
@@ -152,13 +148,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<TResult> function, CancellationToken cancellationToken)
: this(function, null, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -179,12 +172,9 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<TResult> function, TaskCreationOptions creationOptions)
: this(function, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -209,12 +199,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(function, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -228,13 +215,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentException">
/// The <paramref name="function"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<object, TResult> function, object state)
: this(function, state, null, default(CancellationToken),
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -252,13 +236,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<object, TResult> function, object state, CancellationToken cancellationToken)
: this(function, state, null, cancellationToken,
TaskCreationOptions.None, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -280,13 +261,10 @@ namespace System.Threading.Tasks
/// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
: this(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken),
creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
}
@@ -313,23 +291,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task(Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
: this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
creationOptions, InternalTaskOptions.None, null)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- PossiblyCaptureContext(ref stackMark);
- }
-
- internal Task(
- Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler,
- ref StackCrawlMark stackMark) :
- this(valueSelector, parent, cancellationToken,
- creationOptions, internalOptions, scheduler)
- {
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -341,24 +306,10 @@ namespace System.Threading.Tasks
/// <param name="cancellationToken">The CancellationToken for the task.</param>
/// <param name="creationOptions">Options to control the future's behavior.</param>
/// <param name="internalOptions">Internal options to control the future's behavior.</param>
- /// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="creationOptions"/> argument specifies
- /// a SelfReplicating <see cref="Task{TResult}"/>, which is illegal."/>.</exception>
internal Task(Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
- if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
- {
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
- }
- }
-
- internal Task(
- Func<object, TResult> valueSelector, object state, Task parent, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark) :
- this(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
- {
- PossiblyCaptureContext(ref stackMark);
}
/// <summary>
@@ -371,22 +322,16 @@ namespace System.Threading.Tasks
/// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
/// <param name="creationOptions">Options to control the future's behavior.</param>
/// <param name="internalOptions">Internal options to control the future's behavior.</param>
- /// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="creationOptions"/> argument specifies
- /// a SelfReplicating <see cref="Task{TResult}"/>, which is illegal."/>.</exception>
internal Task(Delegate valueSelector, object state, Task parent, CancellationToken cancellationToken,
TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
{
- if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
- {
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
- }
}
// Internal method used by TaskFactory<TResult>.StartNew() methods
internal static Task<TResult> StartNew(Task parent, Func<TResult> function, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
{
if (function == null)
{
@@ -396,13 +341,9 @@ namespace System.Threading.Tasks
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
}
- if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
- {
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
- }
// Create and schedule the future.
- Task<TResult> f = new Task<TResult>(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler, ref stackMark);
+ Task<TResult> f = new Task<TResult>(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
f.ScheduleAndStart(false);
return f;
@@ -410,7 +351,7 @@ namespace System.Threading.Tasks
// Internal method used by TaskFactory<TResult>.StartNew() methods
internal static Task<TResult> StartNew(Task parent, Func<object, TResult> function, object state, CancellationToken cancellationToken,
- TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
{
if (function == null)
{
@@ -420,13 +361,9 @@ namespace System.Threading.Tasks
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
}
- if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
- {
- ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
- }
// Create and schedule the future.
- Task<TResult> f = new Task<TResult>(function, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler, ref stackMark);
+ Task<TResult> f = new Task<TResult>(function, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
f.ScheduleAndStart(false);
return f;
@@ -726,11 +663,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -754,11 +689,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -784,11 +717,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -819,11 +750,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -864,17 +793,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>> continuationAction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, only with a stack mark.
internal Task ContinueWith(Action<Task<TResult>> continuationAction, TaskScheduler scheduler, CancellationToken cancellationToken,
- TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ TaskContinuationOptions continuationOptions)
{
if (continuationAction == null)
{
@@ -895,8 +822,7 @@ namespace System.Threading.Tasks
Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
this, continuationAction, null,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -926,11 +852,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationAction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -955,11 +879,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state,CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
@@ -986,11 +908,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -1022,11 +942,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state,TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -1068,17 +986,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, only with a stack mark.
internal Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskScheduler scheduler, CancellationToken cancellationToken,
- TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ TaskContinuationOptions continuationOptions)
{
if (continuationAction == null)
{
@@ -1099,8 +1015,7 @@ namespace System.Threading.Tasks
Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
this, continuationAction, state,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -1133,11 +1048,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -1164,11 +1077,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
@@ -1196,11 +1107,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -1240,11 +1149,9 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -1295,17 +1202,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken,
TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark.
internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler,
- CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null)
{
@@ -1326,8 +1231,7 @@ namespace System.Threading.Tasks
Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult,TNewResult>(
this, continuationFunction, null,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may
@@ -1360,11 +1264,9 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="continuationFunction"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None);
}
@@ -1392,12 +1294,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
CancellationToken cancellationToken)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None);
}
/// <summary>
@@ -1426,12 +1326,10 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ArgumentNullException">
/// The <paramref name="scheduler"/> argument is null.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None);
}
/// <summary>
@@ -1472,12 +1370,10 @@ namespace System.Threading.Tasks
/// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
/// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
TaskContinuationOptions continuationOptions)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions);
}
/// <summary>
@@ -1529,17 +1425,15 @@ namespace System.Threading.Tasks
/// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
/// has already been disposed.
/// </exception>
- [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
{
- StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
- return ContinueWith<TNewResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ return ContinueWith<TNewResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions);
}
// Same as the above overload, just with a stack mark.
internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
- TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions)
{
if (continuationFunction == null)
{
@@ -1560,8 +1454,7 @@ namespace System.Threading.Tasks
Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult,TNewResult>(
this, continuationFunction, state,
- creationOptions, internalOptions,
- ref stackMark
+ creationOptions, internalOptions
);
// Register the continuation. If synchronous execution is requested, this may