Imported Upstream version 5.4.0.167

Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-08-21 15:34:15 +00:00
parent e49d6f06c0
commit 536cd135cc
12856 changed files with 563812 additions and 223249 deletions

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.0.3.0</AssemblyVersion>
<AssemblyKey>MSFT</AssemblyKey>
<IsNETCoreApp>true</IsNETCoreApp>
<IsUAP>true</IsUAP>
</PropertyGroup>
</Project>
</Project>

View File

@ -1 +1 @@
8c3cad7427c3de2c506f3bfce13e01c50680c612
671122ad9b0b9cf5402090153b5999e24d96ea14

View File

@ -8,9 +8,8 @@
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
#pragma warning disable 0420
namespace System.Threading.Tasks
@ -18,6 +17,7 @@ namespace System.Threading.Tasks
/// <summary>
/// Represents an index range
/// </summary>
[StructLayout(LayoutKind.Auto)]
internal struct IndexRange
{
// the From and To values for this range. These do not change.
@ -26,7 +26,11 @@ namespace System.Threading.Tasks
// 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.
// All updates to this field need to be interlocked. To avoid split interlockeds across cache-lines
// in 32-bit processes, in 32-bit processes when the range fits in a 32-bit value, we prefer to use
// a 32-bit field, and just use the first 32-bits of the long. And to minimize false sharing, each
// value is stored in its own heap-allocated object, which is lazily allocated by the thread using
// that range, minimizing the chances it'll be near the objects from other threads.
internal volatile Box<long> _nSharedCurrentIndexOffset;
// to be set to 1 by the worker that finishes this range. It's OK to do a non-interlocked write here.
@ -37,6 +41,7 @@ namespace System.Threading.Tasks
/// <summary>
/// The RangeWorker struct wraps the state needed by a task that services the parallel loop
/// </summary>
[StructLayout(LayoutKind.Auto)]
internal struct RangeWorker
{
// reference to the IndexRange array allocated by the range manager
@ -54,15 +59,19 @@ namespace System.Threading.Tasks
// the increment value is doubled each time this worker finds work, and is capped at this value
internal readonly long _nMaxIncrementValue;
// whether to use 32-bits or 64-bits of current index in each range
internal readonly bool _use32BitCurrentIndex;
internal bool IsInitialized { get { return _indexRanges != null; } }
/// <summary>
/// Initializes a RangeWorker struct
/// </summary>
internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep)
internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep, bool use32BitCurrentIndex)
{
_indexRanges = ranges;
_use32BitCurrentIndex = use32BitCurrentIndex;
_nCurrentIndexRange = nInitialRange;
_nStep = nStep;
@ -99,9 +108,24 @@ namespace System.Threading.Tasks
Interlocked.CompareExchange(ref _indexRanges[_nCurrentIndexRange]._nSharedCurrentIndexOffset, new Box<long>(0), null);
}
// this access needs to be on the array slot
long nMyOffset = Interlocked.Add(ref _indexRanges[_nCurrentIndexRange]._nSharedCurrentIndexOffset.Value,
_nIncrementValue) - _nIncrementValue;
long nMyOffset;
if (IntPtr.Size == 4 && _use32BitCurrentIndex)
{
// In 32-bit processes, we prefer to use 32-bit interlocked operations, to avoid the possibility of doing
// a 64-bit interlocked when the target value crosses a cache line, as that can be super expensive.
// We use the first 32 bits of the Int64 index in such cases.
unsafe
{
fixed (long* indexPtr = &_indexRanges[_nCurrentIndexRange]._nSharedCurrentIndexOffset.Value)
{
nMyOffset = Interlocked.Add(ref *(int*)indexPtr, (int)_nIncrementValue) - _nIncrementValue;
}
}
}
else
{
nMyOffset = Interlocked.Add(ref _indexRanges[_nCurrentIndexRange]._nSharedCurrentIndexOffset.Value, _nIncrementValue) - _nIncrementValue;
}
if (currentRange._nToExclusive - currentRange._nFromInclusive > nMyOffset)
{
@ -182,6 +206,7 @@ namespace System.Threading.Tasks
internal class RangeManager
{
internal readonly IndexRange[] _indexRanges;
internal readonly bool _use32BitCurrentIndex;
internal int _nCurrentIndexRangeToAssign;
internal long _nStep;
@ -229,6 +254,7 @@ namespace System.Threading.Tasks
// 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;
_use32BitCurrentIndex = IntPtr.Size == 4 && nRangeSize <= int.MaxValue;
// allocate the array of index ranges
_indexRanges = new IndexRange[nNumRanges];
@ -269,7 +295,7 @@ namespace System.Threading.Tasks
int nInitialRange = (Interlocked.Increment(ref _nCurrentIndexRangeToAssign) - 1) % _indexRanges.Length;
return new RangeWorker(_indexRanges, nInitialRange, _nStep);
return new RangeWorker(_indexRanges, nInitialRange, _nStep, _use32BitCurrentIndex);
}
}
}

View File

@ -79,7 +79,7 @@ namespace System.Threading.Tasks
if (userActionYieldedBeforeCompletion)
{
_pendingTask = new Task(s => ((Replica)s).Execute(), this, CancellationToken.None, TaskCreationOptions.PreferFairness);
_pendingTask = new Task(s => ((Replica)s).Execute(), this, CancellationToken.None, TaskCreationOptions.None);
_pendingTask.Start(_replicator._scheduler);
}
else

View File

@ -15,7 +15,8 @@ namespace System.Threading.Tasks.Tests
[Fact]
public static void TestEtw()
{
using (var listener = new TestEventListener("System.Threading.Tasks.Parallel.EventSource", EventLevel.Verbose))
var eventSourceName = PlatformDetection.IsFullFramework ? "System.Threading.Tasks.TplEventSource" : "System.Threading.Tasks.Parallel.EventSource";
using (var listener = new TestEventListener(eventSourceName, EventLevel.Verbose))
{
var events = new ConcurrentQueue<int>();
listener.RunWithCallback(ev => events.Enqueue(ev.EventId), () => {

View File

@ -2,9 +2,11 @@
// 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.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security;
using Xunit;
@ -18,17 +20,17 @@ namespace System.Threading.Tasks.Tests
{
// ParallelOptions tests
ParallelOptions options = new ParallelOptions();
Assert.Throws<ArgumentOutOfRangeException>("MaxDegreeOfParallelism", () => options.MaxDegreeOfParallelism = 0);
Assert.Throws<ArgumentOutOfRangeException>("MaxDegreeOfParallelism", () => options.MaxDegreeOfParallelism = -2);
AssertExtensions.Throws<ArgumentOutOfRangeException>("MaxDegreeOfParallelism", () => options.MaxDegreeOfParallelism = 0);
AssertExtensions.Throws<ArgumentOutOfRangeException>("MaxDegreeOfParallelism", () => options.MaxDegreeOfParallelism = -2);
// Parallel.Invoke tests
Action[] smallActionArray = new Action[] { () => { } };
Action[] largeActionArray = new Action[15];
for (int i = 0; i < 15; i++) largeActionArray[i] = () => { };
Assert.Throws<ArgumentNullException>("actions", () => Parallel.Invoke((Action[])null));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.Invoke((ParallelOptions)null, () => { }));
Assert.Throws<ArgumentNullException>("actions", () => Parallel.Invoke(options, null));
AssertExtensions.Throws<ArgumentNullException>("actions", () => Parallel.Invoke((Action[])null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.Invoke((ParallelOptions)null, () => { }));
AssertExtensions.Throws<ArgumentNullException>("actions", () => Parallel.Invoke(options, null));
Assert.Throws<ArgumentException>(() => Parallel.Invoke(options, (Action)null));
@ -46,58 +48,58 @@ namespace System.Threading.Tasks.Tests
options = new ParallelOptions(); // Reset to get rid of CT
// Test P.For(from, to, action<int>)
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, (Action<int>)null));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, (Action<int>)null));
// Test P.For(from, to, options, action<int>)
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0, 10, null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, options, (Action<int>)null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0, 10, null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, options, (Action<int>)null));
// Test P.For(from, to, Action<int, ParallelLoopState>)
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, (Action<int, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, (Action<int, ParallelLoopState>)null));
// Test P.For(from, to, options, Action<int, ParallelLoopState>)
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0, 10, null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, options, (Action<int, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0, 10, null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, options, (Action<int, ParallelLoopState>)null));
// Test P.For<TLocal>(from, to, Func<TLocal>, Func<int, PLS, TLocal, TLocal>, Action<TLocal>)
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.For(0, 10, (Func<string>)null, (a, b, c) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, () => "", null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0, 10, () => "", (a, b, c) => "", null));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.For(0, 10, (Func<string>)null, (a, b, c) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, () => "", null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0, 10, () => "", (a, b, c) => "", null));
// Test P.For<TLocal>(from, to, options, Func<TLocal>, Func<int, PLS, TLocal, TLocal>, Action<TLocal>)
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0, 10, null, () => "", (a, b, c) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.For(0, 10, options, (Func<string>)null, (a, b, c) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, options, () => "", null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0, 10, options, () => "", (a, b, c) => "", null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0, 10, null, () => "", (a, b, c) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.For(0, 10, options, (Func<string>)null, (a, b, c) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0, 10, options, () => "", null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0, 10, options, () => "", (a, b, c) => "", null));
//
// Parallel.For(64) tests
//
// Test P.For(from, to, Action<long>)
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, (Action<long>)null));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, (Action<long>)null));
// Test P.For(from, to, options, Action<long>)
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0L, 10L, null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, options, (Action<long>)null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0L, 10L, null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, options, (Action<long>)null));
// Test P.For(from, to, Action<long, PLS>)
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, (Action<long, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, (Action<long, ParallelLoopState>)null));
// Test P.For(from, to, options, Action<long, PLS>)
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0L, 10L, null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, options, (Action<long, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0L, 10L, null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, options, (Action<long, ParallelLoopState>)null));
// Test P.For<TLocal>(from, to, Func<TLocal>, Func<long, PLS, TLocal, TLocal>, Action<TLocal>)
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.For(0L, 10L, (Func<string>)null, (a, b, c) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, () => "", null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0L, 10L, () => "", (a, b, c) => "", null));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.For(0L, 10L, (Func<string>)null, (a, b, c) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, () => "", null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0L, 10L, () => "", (a, b, c) => "", null));
// Test P.For<TLocal>(from, to, options, Func<TLocal>, Func<long, PLS, TLocal, TLocal>, Action<TLocal>)
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0L, 10L, null, () => "", (a, b, c) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.For(0L, 10L, options, (Func<string>)null, (a, b, c) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, options, () => "", null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0L, 10L, options, () => "", (a, b, c) => "", null));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.For(0L, 10L, null, () => "", (a, b, c) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.For(0L, 10L, options, (Func<string>)null, (a, b, c) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.For(0L, 10L, options, () => "", null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.For(0L, 10L, options, () => "", (a, b, c) => "", null));
// Check that we properly handle pre-canceled requests
options.CancellationToken = cts.Token;
@ -113,57 +115,57 @@ namespace System.Threading.Tasks.Tests
// Test P.FE<T>(IE<T>, Action<T>)
string[] sArray = new string[] { "one", "two", "three" };
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, (Action<string>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, (Action<string>)null));
// Test P.FE<T>(IE<T>, options, Action<T>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, _ => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, (Action<string>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, (Action<string>)null));
// Test P.FE<T>(IE<T>, Action<T,ParallelLoopState>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, (_, state) => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, (Action<string, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, (_, state) => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, (Action<string, ParallelLoopState>)null));
// Test P.FE<T>(IE<T>, options, Action<T,ParallelLoopState>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, (_, state) => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, (_, state) => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, (Action<string, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, (_, state) => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, (_, state) => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, (Action<string, ParallelLoopState>)null));
// Test P.FE<T>(IE<T>, Action<T,ParallelLoopState,idx>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, (_, state, idx) => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, (Action<string, ParallelLoopState, long>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, (_, state, idx) => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, (Action<string, ParallelLoopState, long>)null));
// Test P.FE<T>(IE<T>, options, Action<T,ParallelLoopState,idx>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, (_, state, idx) => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, (_, state, idx) => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, (Action<string, ParallelLoopState, long>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, (_, state, idx) => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, (_, state, idx) => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, (Action<string, ParallelLoopState, long>)null));
//Test P.FE<T,L>(IE<T>, Func<L>, Func<T,PLS,L,L>, Action<L>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, () => "", (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, (Func<string>)null, (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, () => "", (_, state, local) => "", null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, () => "", (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, (Func<string>)null, (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, () => "", (_, state, local) => "", null));
//Test P.FE<T,L>(IE<T>, options, Func<L>, Func<T,PLS,L,L>, Action<L>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, () => "", (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, () => "", (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, options, (Func<string>)null, (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, options, () => "", (_, state, local) => "", null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, () => "", (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, () => "", (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, options, (Func<string>)null, (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, options, () => "", (_, state, local) => "", null));
//Test P.FE<T,L>(IE<T>, Func<L>, Func<T,PLS,long,L,L>, Action<L>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, () => "", (_, state, idx, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, (Func<string>)null, (_, state, idx, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, () => "", (Func<string, ParallelLoopState, long, string, string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, () => "", (_, state, idx, local) => "", null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, () => "", (_, state, idx, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, (Func<string>)null, (_, state, idx, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, () => "", (Func<string, ParallelLoopState, long, string, string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, () => "", (_, state, idx, local) => "", null));
//Test P.FE<T,L>(IE<T>, options, Func<L>, Func<T,PLS,idx,L,L>, Action<L>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, () => "", (_, state, idx, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, () => "", (_, state, idx, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, options, (Func<string>)null, (_, state, idx, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, () => "", (Func<string, ParallelLoopState, long, string, string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, options, () => "", (_, state, idx, local) => "", null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((IEnumerable<string>)null, options, () => "", (_, state, idx, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(sArray, null, () => "", (_, state, idx, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(sArray, options, (Func<string>)null, (_, state, idx, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(sArray, options, () => "", (Func<string, ParallelLoopState, long, string, string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(sArray, options, () => "", (_, state, idx, local) => "", null));
//
// Parallel.ForEach(Partitioner) tests
@ -172,35 +174,35 @@ namespace System.Threading.Tasks.Tests
var partitioner = Partitioner.Create(sArray);
// Test P.FE<T>(Partitioner<T>, Action<T>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), (Action<string>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), (Action<string>)null));
// Test P.FE<T>(Partitioner<T>, options, Action<T>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, options, _ => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(Partitioner.Create(sArray), null, _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), options, (Action<string>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, options, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(Partitioner.Create(sArray), null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), options, (Action<string>)null));
// Test P.FE<T>(Partitioner<T>, Action<T,ParallelLoopState>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, (_, state) => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), (Action<string, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, (_, state) => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), (Action<string, ParallelLoopState>)null));
// Test P.FE<T>(Partitioner<T>, options, Action<T,ParallelLoopState>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, options, (_, state) => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(Partitioner.Create(sArray), null, (_, state) => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), options, (Action<string, ParallelLoopState>)null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, options, (_, state) => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(Partitioner.Create(sArray), null, (_, state) => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), options, (Action<string, ParallelLoopState>)null));
//Test P.FE<T,L>(Partitioner<T>, Func<L>, Func<T,PLS,L,L>, Action<L>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, () => "", (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(Partitioner.Create(sArray), (Func<string>)null, (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(Partitioner.Create(sArray), () => "", (_, state, local) => "", null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, () => "", (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(Partitioner.Create(sArray), (Func<string>)null, (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(Partitioner.Create(sArray), () => "", (_, state, local) => "", null));
//Test P.FE<T,L>(Partitioner<T>, options, Func<L>, Func<T,PLS,L,L>, Action<L>)
Assert.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, options, () => "", (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(Partitioner.Create(sArray), null, () => "", (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(Partitioner.Create(sArray), options, (Func<string>)null, (_, state, local) => "", _ => { }));
Assert.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), options, () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
Assert.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(Partitioner.Create(sArray), options, () => "", (_, state, local) => "", null));
AssertExtensions.Throws<ArgumentNullException>("source", () => Parallel.ForEach((Partitioner<string>)null, options, () => "", (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("parallelOptions", () => Parallel.ForEach(Partitioner.Create(sArray), null, () => "", (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localInit", () => Parallel.ForEach(Partitioner.Create(sArray), options, (Func<string>)null, (_, state, local) => "", _ => { }));
AssertExtensions.Throws<ArgumentNullException>("body", () => Parallel.ForEach(Partitioner.Create(sArray), options, () => "", (Func<string, ParallelLoopState, string, string>)null, _ => { }));
AssertExtensions.Throws<ArgumentNullException>("localFinally", () => Parallel.ForEach(Partitioner.Create(sArray), options, () => "", (_, state, local) => "", null));
}
// Cover converting P.ForEaches of arrays, lists to P.Fors
@ -1226,6 +1228,138 @@ namespace System.Threading.Tasks.Tests
Assert.False(withinTaskId == null || withinTaskId < 0, "Task.CurrentId called from within a Task must be non-negative");
}
private const int CancelForTestLoopIterations = 500;
private static void VerifyCancelTestState(
bool gotCancellationException,
bool reportedAsCompleted,
int actuallyCompletedCount)
{
Assert.Equal(reportedAsCompleted, !gotCancellationException);
if (reportedAsCompleted)
{
Assert.Equal(CancelForTestLoopIterations, actuallyCompletedCount);
}
}
[Fact]
public static void CancelForIntTest()
{
for (int i = 0; i < 100; ++i)
{
var cancellationTokenSource = new CancellationTokenSource();
bool gotCancellationException = false;
bool reportedAsCompleted = false;
var parallelOptions = new ParallelOptions { CancellationToken = cancellationTokenSource.Token };
int completedCount = 0;
try
{
reportedAsCompleted =
Parallel.For(
0,
CancelForTestLoopIterations,
parallelOptions,
value =>
{
Interlocked.Increment(ref completedCount);
if (!cancellationTokenSource.IsCancellationRequested)
{
Task.Run(() => cancellationTokenSource.Cancel());
}
}).IsCompleted;
}
catch (OperationCanceledException)
{
gotCancellationException = true;
}
int actuallyCompletedCount = Interlocked.CompareExchange(ref completedCount, 0, 0);
VerifyCancelTestState(gotCancellationException, reportedAsCompleted, actuallyCompletedCount);
}
}
[Fact]
public static void CancelForLongTest()
{
for (int i = 0; i < 100; ++i)
{
var cancellationTokenSource = new CancellationTokenSource();
bool gotCancellationException = false;
bool reportedAsCompleted = false;
var parallelOptions = new ParallelOptions { CancellationToken = cancellationTokenSource.Token };
int completedCount = 0;
try
{
reportedAsCompleted =
Parallel.For(
(long)0,
(long)CancelForTestLoopIterations,
parallelOptions,
value =>
{
Interlocked.Increment(ref completedCount);
if (!cancellationTokenSource.IsCancellationRequested)
{
Task.Run(() => cancellationTokenSource.Cancel());
}
}).IsCompleted;
}
catch (OperationCanceledException)
{
gotCancellationException = true;
}
int actuallyCompletedCount = Interlocked.CompareExchange(ref completedCount, 0, 0);
VerifyCancelTestState(gotCancellationException, reportedAsCompleted, actuallyCompletedCount);
}
}
private static IEnumerable<object[]> CancelForEachTest_MemberData()
{
var array = new int[CancelForTestLoopIterations];
yield return new object[] { array };
yield return new object[] { array.Select(i => i) };
}
[Theory]
[MemberData(nameof(CancelForEachTest_MemberData))]
public static void CancelForEachTest(IEnumerable<int> enumerable)
{
for (int i = 0; i < 100; ++i)
{
var cancellationTokenSource = new CancellationTokenSource();
bool gotCancellationException = false;
bool reportedAsCompleted = false;
var parallelOptions = new ParallelOptions { CancellationToken = cancellationTokenSource.Token };
int completedCount = 0;
try
{
reportedAsCompleted =
Parallel.ForEach(
enumerable,
parallelOptions,
value =>
{
Interlocked.Increment(ref completedCount);
if (!cancellationTokenSource.IsCancellationRequested)
{
Task.Run(() => cancellationTokenSource.Cancel());
}
}).IsCompleted;
}
catch (OperationCanceledException)
{
gotCancellationException = true;
}
int actuallyCompletedCount = Interlocked.CompareExchange(ref completedCount, 0, 0);
VerifyCancelTestState(gotCancellationException, reportedAsCompleted, actuallyCompletedCount);
}
}
#region Helper Classes and Methods
// Just adds the contents of an auto-generated list inside a foreach loop.

View File

@ -11,9 +11,15 @@
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Compile Include="$(CommonTestPath)\System\AssertExtensions.cs">
<Link>Common\System\AssertExtensions.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\Diagnostics\Tracing\TestEventListener.cs">
<Link>Common\System\Diagnostics\Tracing\TestEventListener.cs</Link>
</Compile>
<Compile Include="$(CommonTestPath)\System\PlatformDetection.cs">
<Link>Common\System\PlatformDetection.cs</Link>
</Compile>
<Compile Include="BreakTests.cs" />
<Compile Include="EtwTests.cs" />
<Compile Include="ParallelFor.cs" />