Imported Upstream version 5.0.0.42

Former-commit-id: fd56571888259555122d8a0f58c68838229cea2b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2017-04-10 11:41:01 +00:00
parent 1190d13a04
commit 6bdd276d05
19939 changed files with 3099680 additions and 93811 deletions

View File

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks.Parallel.Tests", "tests\System.Threading.Tasks.Parallel.Tests.csproj", "{DE29C320-2ECA-43FD-9F41-6F4F6C6BACD5}"
ProjectSection(ProjectDependencies) = postProject
{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F} = {A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks.Parallel", "src\System.Threading.Tasks.Parallel.csproj", "{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{47919FF5-DA40-4D99-AF2D-F560282AA913}"
ProjectSection(SolutionItems) = preProject
..\.nuget\packages.Windows_NT.config = ..\.nuget\packages.Windows_NT.config
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU = DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU
ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU = ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DE29C320-2ECA-43FD-9F41-6F4F6C6BACD5}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{DE29C320-2ECA-43FD-9F41-6F4F6C6BACD5}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{DE29C320-2ECA-43FD-9F41-6F4F6C6BACD5}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{DE29C320-2ECA-43FD-9F41-6F4F6C6BACD5}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Debug|Any CPU
{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}.DebugNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Debug|Any CPU
{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.ActiveCfg = netcoreapp-Release|Any CPU
{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}.ReleaseNETCoreAppnetcoreappnetcoreapp|AnyCPU.Build.0 = netcoreapp-Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,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>
<IsNETCoreApp>true</IsNETCoreApp>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netcoreapp;
uap;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,71 @@
// 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.
// ------------------------------------------------------------------------------
// Changes to this file must follow the http://aka.ms/api-review process.
// ------------------------------------------------------------------------------
namespace System.Threading.Tasks
{
public static partial class Parallel
{
public static System.Threading.Tasks.ParallelLoopResult For(int fromInclusive, int toExclusive, System.Action<int, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(int fromInclusive, int toExclusive, System.Action<int> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(int fromInclusive, int toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<int, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(int fromInclusive, int toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<int> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(long fromInclusive, long toExclusive, System.Action<long, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(long fromInclusive, long toExclusive, System.Action<long> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(long fromInclusive, long toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<long, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For(long fromInclusive, long toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<long> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, System.Func<TLocal> localInit, System.Func<int, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Func<TLocal> localInit, System.Func<int, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For<TLocal>(long fromInclusive, long toExclusive, System.Func<TLocal> localInit, System.Func<long, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult For<TLocal>(long fromInclusive, long toExclusive, System.Threading.Tasks.ParallelOptions parallelOptions, System.Func<TLocal> localInit, System.Func<long, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Concurrent.OrderablePartitioner<TSource> source, System.Action<TSource, System.Threading.Tasks.ParallelLoopState, long> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Concurrent.OrderablePartitioner<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<TSource, System.Threading.Tasks.ParallelLoopState, long> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Concurrent.Partitioner<TSource> source, System.Action<TSource, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Concurrent.Partitioner<TSource> source, System.Action<TSource> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Concurrent.Partitioner<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<TSource, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Concurrent.Partitioner<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<TSource> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Generic.IEnumerable<TSource> source, System.Action<TSource, System.Threading.Tasks.ParallelLoopState, long> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Generic.IEnumerable<TSource> source, System.Action<TSource, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Generic.IEnumerable<TSource> source, System.Action<TSource> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Generic.IEnumerable<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<TSource, System.Threading.Tasks.ParallelLoopState, long> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Generic.IEnumerable<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<TSource, System.Threading.Tasks.ParallelLoopState> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource>(System.Collections.Generic.IEnumerable<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Action<TSource> body) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Concurrent.OrderablePartitioner<TSource> source, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, long, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Concurrent.OrderablePartitioner<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, long, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Concurrent.Partitioner<TSource> source, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Concurrent.Partitioner<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Generic.IEnumerable<TSource> source, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Generic.IEnumerable<TSource> source, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, long, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Generic.IEnumerable<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static System.Threading.Tasks.ParallelLoopResult ForEach<TSource, TLocal>(System.Collections.Generic.IEnumerable<TSource> source, System.Threading.Tasks.ParallelOptions parallelOptions, System.Func<TLocal> localInit, System.Func<TSource, System.Threading.Tasks.ParallelLoopState, long, TLocal, TLocal> body, System.Action<TLocal> localFinally) { throw null; }
public static void Invoke(params System.Action[] actions) { }
public static void Invoke(System.Threading.Tasks.ParallelOptions parallelOptions, params System.Action[] actions) { }
}
[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
public partial struct ParallelLoopResult
{
public bool IsCompleted { get { throw null; } }
public System.Nullable<long> LowestBreakIteration { get { throw null; } }
}
public partial class ParallelLoopState
{
internal ParallelLoopState() { }
public bool IsExceptional { get { throw null; } }
public bool IsStopped { get { throw null; } }
public System.Nullable<long> LowestBreakIteration { get { throw null; } }
public bool ShouldExitCurrentIteration { get { throw null; } }
public void Break() { }
public void Stop() { }
}
public partial class ParallelOptions
{
public ParallelOptions() { }
public System.Threading.CancellationToken CancellationToken { get { throw null; } set { } }
public int MaxDegreeOfParallelism { get { throw null; } set { } }
public System.Threading.Tasks.TaskScheduler TaskScheduler { get { throw null; } set { } }
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System.Threading.Tasks.Parallel.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\System.Runtime\ref\System.Runtime.csproj" />
<ProjectReference Include="..\..\System.Collections.Concurrent\ref\System.Collections.Concurrent.csproj" />
<ProjectReference Include="..\..\System.Threading.Tasks\ref\System.Threading.Tasks.csproj" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netcoreapp;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Parallel_Invoke_ActionNull" xml:space="preserve">
<value>One of the actions was null.</value>
</data>
<data name="Parallel_ForEach_OrderedPartitionerKeysNotNormalized" xml:space="preserve">
<value>This method requires the use of an OrderedPartitioner with the KeysNormalized property set to true.</value>
</data>
<data name="Parallel_ForEach_PartitionerNotDynamic" xml:space="preserve">
<value>The Partitioner used here must support dynamic partitioning.</value>
</data>
<data name="Parallel_ForEach_PartitionerReturnedNull" xml:space="preserve">
<value>The Partitioner used here returned a null partitioner source.</value>
</data>
<data name="Parallel_ForEach_NullEnumerator" xml:space="preserve">
<value>The Partitioner source returned a null enumerator.</value>
</data>
<data name="ParallelState_Break_InvalidOperationException_BreakAfterStop" xml:space="preserve">
<value>Break was called after Stop was called.</value>
</data>
<data name="ParallelState_Stop_InvalidOperationException_StopAfterBreak" xml:space="preserve">
<value>Stop was called after Break was called.</value>
</data>
<data name="ParallelState_NotSupportedException_UnsupportedMethod" xml:space="preserve">
<value>This method is not supported.</value>
</data>
</root>

View File

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<ProjectGuid>{A6BA5DF2-772E-4DA1-BC2D-89FF4A21EE4F}</ProjectGuid>
<RootNamespace>System.Threading.Tasks.Parallel</RootNamespace>
<AssemblyName>System.Threading.Tasks.Parallel</AssemblyName>
<FileAlignment>512</FileAlignment>
<DefineConstants>$(DefineConstants);CONCURRENT_COLLECTIONS;FEATURE_TRACING</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='netcoreapp-Release|AnyCPU'" />
<ItemGroup>
<Compile Include="System\Threading\PlatformHelper.cs" />
<Compile Include="System\Threading\Tasks\Box.cs" />
<Compile Include="System\Threading\Tasks\Parallel.cs" />
<Compile Include="System\Threading\Tasks\ParallelETWProvider.cs" />
<Compile Include="System\Threading\Tasks\ParallelLoopState.cs" />
<Compile Include="System\Threading\Tasks\ParallelRangeManager.cs" />
<Compile Include="System\Threading\Tasks\TaskReplicator.cs" />
</ItemGroup>
<ItemGroup>
<TargetingPackReference Include="mscorlib" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Diagnostics.Contracts" />
<Reference Include="System.Diagnostics.Debug" />
<Reference Include="System.Diagnostics.Tools" />
<Reference Include="System.Diagnostics.Tracing" />
<Reference Include="System.Resources.ResourceManager" />
<Reference Include="System.Runtime" />
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Threading" />
<Reference Include="System.Threading.Tasks" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>

View File

@ -0,0 +1,34 @@
// 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.
namespace System.Threading
{
/// <summary>
/// A helper class to get the number of preocessors, it updates the numbers of processors every sampling interval
/// </summary>
internal static class PlatformHelper
{
private const Int32 PROCESSOR_COUNT_REFRESH_INTERVAL_MS = 30000; // How often to refresh the count, in milliseconds.
private static volatile Int32 s_processorCount; // The last count seen.
private static volatile Int32 s_lastProcessorCountRefreshTicks; // The last time we refreshed.
/// <summary>
/// Gets the number of available processors
/// </summary>
internal static Int32 ProcessorCount
{
get
{
Int32 now = Environment.TickCount;
if (s_processorCount == 0 || (now - s_lastProcessorCountRefreshTicks) >= PROCESSOR_COUNT_REFRESH_INTERVAL_MS)
{
s_processorCount = Environment.ProcessorCount;
s_lastProcessorCountRefreshTicks = now;
}
return s_processorCount;
}
}
} // class PlatformHelper
} // namespace

View File

@ -0,0 +1,19 @@
// 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;
namespace System.Threading.Tasks
{
/// <summary>Utility class for allocating value types as heap variables.</summary>
internal class Box<T>
{
internal T Value;
internal Box(T value)
{
this.Value = value;
}
} // class Box<T>
} // namespace

View File

@ -0,0 +1 @@
303dd2a6dafd2740261ab8816f1920ec6acc56ca

View File

@ -0,0 +1,264 @@
// 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.
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// EventSource for Task.Parallel.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System;
using System.Collections.Generic;
using System.Text;
using System.Security;
using System.Diagnostics.Tracing;
namespace System.Threading.Tasks
{
/// <summary>Provides an event source for tracing TPL information.</summary>
[EventSource(Name = "System.Threading.Tasks.Parallel.EventSource")]
internal sealed class ParallelEtwProvider : EventSource
{
/// <summary>
/// Defines the singleton instance for the Task.Parallel ETW provider.
/// </summary>
public static readonly ParallelEtwProvider Log = new ParallelEtwProvider();
/// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
private ParallelEtwProvider() { }
/// <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>ETW tasks that have start/stop events.</summary>
public class Tasks
{ // this name is important for EventSource
/// <summary>A parallel loop.</summary>
public const EventTask Loop = (EventTask)1;
/// <summary>A parallel invoke.</summary>
public const EventTask Invoke = (EventTask)2;
// Do not use 3, it is used for "TaskExecute" in the TPL provider.
// Do not use 4, it is used for "TaskWait" in the TPL provider.
/// <summary>A fork/join task within a loop or invoke.</summary>
public const EventTask ForkJoin = (EventTask)5;
}
/// <summary>Enabled for all keywords.</summary>
private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1);
//-----------------------------------------------------------------------------------
//
// TPL Event IDs (must be unique)
//
/// <summary>The beginning of a parallel loop.</summary>
private const Int32 PARALLELLOOPBEGIN_ID = 1;
/// <summary>The ending of a parallel loop.</summary>
private const Int32 PARALLELLOOPEND_ID = 2;
/// <summary>The beginning of a parallel invoke.</summary>
private const Int32 PARALLELINVOKEBEGIN_ID = 3;
/// <summary>The ending of a parallel invoke.</summary>
private const Int32 PARALLELINVOKEEND_ID = 4;
/// <summary>A task entering a fork/join construct.</summary>
private const Int32 PARALLELFORK_ID = 5;
/// <summary>A task leaving a fork/join construct.</summary>
private const Int32 PARALLELJOIN_ID = 6;
//-----------------------------------------------------------------------------------
//
// 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>
[SecuritySafeCritical]
[Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, Task = ParallelEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)]
public void ParallelLoopBegin(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
Int32 ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
Int64 InclusiveFrom, Int64 ExclusiveTo)
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
// 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(Int32);
eventPayload[0].DataPointer = ((IntPtr)(&OriginatingTaskSchedulerID));
eventPayload[1].Size = sizeof(Int32);
eventPayload[1].DataPointer = ((IntPtr)(&OriginatingTaskID));
eventPayload[2].Size = sizeof(Int32);
eventPayload[2].DataPointer = ((IntPtr)(&ForkJoinContextID));
eventPayload[3].Size = sizeof(Int32);
eventPayload[3].DataPointer = ((IntPtr)(&OperationType));
eventPayload[4].Size = sizeof(Int64);
eventPayload[4].DataPointer = ((IntPtr)(&InclusiveFrom));
eventPayload[5].Size = sizeof(Int64);
eventPayload[5].DataPointer = ((IntPtr)(&ExclusiveTo));
WriteEventCore(PARALLELLOOPBEGIN_ID, 6, eventPayload);
}
}
}
#endregion ParallelLoopBegin
#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>
[SecuritySafeCritical]
[Event(PARALLELLOOPEND_ID, Level = EventLevel.Informational, Task = ParallelEtwProvider.Tasks.Loop, Opcode = EventOpcode.Stop)]
public void ParallelLoopEnd(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
Int32 ForkJoinContextID, Int64 TotalIterations)
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
// 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(Int32);
eventPayload[0].DataPointer = ((IntPtr)(&OriginatingTaskSchedulerID));
eventPayload[1].Size = sizeof(Int32);
eventPayload[1].DataPointer = ((IntPtr)(&OriginatingTaskID));
eventPayload[2].Size = sizeof(Int32);
eventPayload[2].DataPointer = ((IntPtr)(&ForkJoinContextID));
eventPayload[3].Size = sizeof(Int64);
eventPayload[3].DataPointer = ((IntPtr)(&TotalIterations));
WriteEventCore(PARALLELLOOPEND_ID, 4, eventPayload);
}
}
}
#endregion ParallelLoopEnd
#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>
[SecuritySafeCritical]
[Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, Task = ParallelEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)]
public void ParallelInvokeBegin(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
Int32 ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
Int32 ActionCount)
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
{
// 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(Int32);
eventPayload[0].DataPointer = ((IntPtr)(&OriginatingTaskSchedulerID));
eventPayload[1].Size = sizeof(Int32);
eventPayload[1].DataPointer = ((IntPtr)(&OriginatingTaskID));
eventPayload[2].Size = sizeof(Int32);
eventPayload[2].DataPointer = ((IntPtr)(&ForkJoinContextID));
eventPayload[3].Size = sizeof(Int32);
eventPayload[3].DataPointer = ((IntPtr)(&OperationType));
eventPayload[4].Size = sizeof(Int32);
eventPayload[4].DataPointer = ((IntPtr)(&ActionCount));
WriteEventCore(PARALLELINVOKEBEGIN_ID, 5, eventPayload);
}
}
}
#endregion ParallelInvokeBegin
#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 = ParallelEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Stop)]
public void ParallelInvokeEnd(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
Int32 ForkJoinContextID)
{
if (IsEnabled(EventLevel.Informational, ALL_KEYWORDS))
WriteEvent(PARALLELINVOKEEND_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
}
#endregion ParallelInvokeEnd
#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, Task = ParallelEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Start)]
public void ParallelFork(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
Int32 ForkJoinContextID)
{
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
WriteEvent(PARALLELFORK_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
}
#endregion ParallelFork
#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 = ParallelEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Stop)]
public void ParallelJoin(Int32 OriginatingTaskSchedulerID, Int32 OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
Int32 ForkJoinContextID)
{
if (IsEnabled(EventLevel.Verbose, ALL_KEYWORDS))
WriteEvent(PARALLELJOIN_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
}
#endregion ParallelJoin
} // class ParallelEtwProvider
} // namespace

View File

@ -0,0 +1,276 @@
// 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;
#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 _nFromInclusive;
internal long _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 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.
internal int _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[] _indexRanges;
// index of the current index range that this worker is grabbing chunks from
internal int _nCurrentIndexRange;
// the step for this loop. Duplicated here for quick access (rather than jumping to rangemanager)
internal long _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 _nIncrementValue;
// the increment value is doubled each time this worker finds work, and is capped at this value
internal readonly long _nMaxIncrementValue;
internal bool IsInitialized { get { return _indexRanges != null; } }
/// <summary>
/// Initializes a RangeWorker struct
/// </summary>
internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep)
{
_indexRanges = ranges;
_nCurrentIndexRange = nInitialRange;
_nStep = nStep;
_nIncrementValue = nStep;
_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 = _indexRanges.Length;
do
{
// local snap to save array access bounds checks in places where we only read fields
IndexRange currentRange = _indexRanges[_nCurrentIndexRange];
if (currentRange._bRangeFinished == 0)
{
if (_indexRanges[_nCurrentIndexRange]._nSharedCurrentIndexOffset == null)
{
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;
if (currentRange._nToExclusive - currentRange._nFromInclusive > nMyOffset)
{
// we found work
nFromInclusiveLocal = currentRange._nFromInclusive + nMyOffset;
nToExclusiveLocal = nFromInclusiveLocal + _nIncrementValue;
// Check for going past end of range, or wrapping
if ((nToExclusiveLocal > currentRange._nToExclusive) || (nToExclusiveLocal < currentRange._nFromInclusive))
{
nToExclusiveLocal = currentRange._nToExclusive;
}
// We will double our unit of increment until it reaches the maximum.
if (_nIncrementValue < _nMaxIncrementValue)
{
_nIncrementValue *= 2;
if (_nIncrementValue > _nMaxIncrementValue)
{
_nIncrementValue = _nMaxIncrementValue;
}
}
return true;
}
else
{
// this index range is completed, mark it so that others can skip it quickly
Interlocked.Exchange(ref _indexRanges[_nCurrentIndexRange]._bRangeFinished, 1);
}
}
// move on to the next index range, in circular order.
_nCurrentIndexRange = (_nCurrentIndexRange + 1) % _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[] _indexRanges;
internal int _nCurrentIndexRangeToAssign;
internal long _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)
{
_nCurrentIndexRangeToAssign = 0;
_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
_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
_indexRanges[i]._nFromInclusive = nCurrentIndex;
_indexRanges[i]._nSharedCurrentIndexOffset = null;
_indexRanges[i]._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.
_indexRanges[i]._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(_indexRanges != null && _indexRanges.Length != 0);
int nInitialRange = (Interlocked.Increment(ref _nCurrentIndexRangeToAssign) - 1) % _indexRanges.Length;
return new RangeWorker(_indexRanges, nInitialRange, _nStep);
}
}
}
#pragma warning restore 0420

View File

@ -0,0 +1,162 @@
// 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.Collections.Concurrent;
using System.Threading.Tasks;
namespace System.Threading.Tasks
{
//
// TaskReplicator runs a delegate inside of one or more Tasks, concurrently. The idea is to exploit "available"
// parallelism, where "available" is determined by the TaskScheduler. We always keep one Task queued to
// the scheduler, and if it starts running we queue another one, etc., up to some (potentially) user-defined
// limit.
//
internal class TaskReplicator
{
public delegate void ReplicatableUserAction<TState>(ref TState replicaState, int timeout, out bool yieldedBeforeCompletion);
private readonly TaskScheduler _scheduler;
private readonly bool _stopOnFirstFailure;
private readonly ConcurrentQueue<Replica> _pendingReplicas = new ConcurrentQueue<Replica>();
private ConcurrentQueue<Exception> _exceptions;
private bool _stopReplicating;
private abstract class Replica
{
protected readonly TaskReplicator _replicator;
protected readonly int _timeout;
protected int _remainingConcurrency;
protected volatile Task _pendingTask; // the most recently queued Task for this replica, or null if we're done.
protected Replica(TaskReplicator replicator, int maxConcurrency, int timeout)
{
_replicator = replicator;
_timeout = timeout;
_remainingConcurrency = maxConcurrency - 1;
_pendingTask = new Task(s => ((Replica)s).Execute(), this);
_replicator._pendingReplicas.Enqueue(this);
}
public void Start()
{
_pendingTask.RunSynchronously(_replicator._scheduler);
}
public void Wait()
{
//
// We wait in a loop because each Task might queue another Task, and so on.
// It's entirely possible for multiple Tasks to be queued without this loop seeing them,
// but that's fine, since we really only need to know when all of them have finished.
//
// Note that it's *very* important that we use Task.Wait here, rather than waiting on some
// other synchronization primitive. Task.Wait can "inline" the Task's execution, on this thread,
// if it hasn't started running on another thread. That's essential for preventing deadlocks,
// in the case where all other threads are blocked for other reasons.
//
Task pendingTask;
while ((pendingTask = _pendingTask) != null)
pendingTask.Wait();
}
public void Execute()
{
try
{
if (!_replicator._stopReplicating && _remainingConcurrency > 0)
{
CreateNewReplica();
_remainingConcurrency = 0; // new replica is responsible for adding concurrency from now on.
}
bool userActionYieldedBeforeCompletion;
ExecuteAction(out userActionYieldedBeforeCompletion);
if (userActionYieldedBeforeCompletion)
{
_pendingTask = new Task(s => ((Replica)s).Execute(), this, CancellationToken.None, TaskCreationOptions.PreferFairness);
_pendingTask.Start(_replicator._scheduler);
}
else
{
_replicator._stopReplicating = true;
_pendingTask = null;
}
}
catch (Exception ex)
{
LazyInitializer.EnsureInitialized(ref _replicator._exceptions).Enqueue(ex);
if (_replicator._stopOnFirstFailure)
_replicator._stopReplicating = true;
_pendingTask = null;
}
}
protected abstract void CreateNewReplica();
protected abstract void ExecuteAction(out bool yieldedBeforeCompletion);
}
private sealed class Replica<TState> : Replica
{
private readonly ReplicatableUserAction<TState> _action;
private TState _state;
public Replica(TaskReplicator replicator, int maxConcurrency, int timeout, ReplicatableUserAction<TState> action)
: base(replicator, maxConcurrency, timeout)
{
_action = action;
}
protected override void CreateNewReplica()
{
Replica<TState> newReplica = new Replica<TState>(_replicator, _remainingConcurrency, GenerateCooperativeMultitaskingTaskTimeout(), _action);
newReplica._pendingTask.Start(_replicator._scheduler);
}
protected override void ExecuteAction(out bool yieldedBeforeCompletion)
{
_action(ref _state, _timeout, out yieldedBeforeCompletion);
}
}
private TaskReplicator(ParallelOptions options, bool stopOnFirstFailure)
{
_scheduler = options.TaskScheduler ?? TaskScheduler.Current;
_stopOnFirstFailure = stopOnFirstFailure;
}
public static void Run<TState>(ReplicatableUserAction<TState> action, ParallelOptions options, bool stopOnFirstFailure)
{
int maxConcurrencyLevel = (options.EffectiveMaxConcurrencyLevel > 0) ? options.EffectiveMaxConcurrencyLevel : int.MaxValue;
TaskReplicator replicator = new TaskReplicator(options, stopOnFirstFailure);
new Replica<TState>(replicator, maxConcurrencyLevel, CooperativeMultitaskingTaskTimeout_RootTask, action).Start();
Replica nextReplica;
while (replicator._pendingReplicas.TryDequeue(out nextReplica))
nextReplica.Wait();
if (replicator._exceptions != null)
throw new AggregateException(replicator._exceptions);
}
private const Int32 CooperativeMultitaskingTaskTimeout_Min = 100; // millisec
private const Int32 CooperativeMultitaskingTaskTimeout_Increment = 50; // millisec
private const Int32 CooperativeMultitaskingTaskTimeout_RootTask = (Int32.MaxValue / 2);
private static Int32 GenerateCooperativeMultitaskingTaskTimeout()
{
// 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.
Int32 period = PlatformHelper.ProcessorCount;
Int32 pseudoRnd = Environment.TickCount;
return CooperativeMultitaskingTaskTimeout_Min + (pseudoRnd % period) * CooperativeMultitaskingTaskTimeout_Increment;
}
}
}

View File

@ -0,0 +1,169 @@
// 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.Collections.Concurrent;
using System.Collections.Generic;
using Xunit;
namespace System.Threading.Tasks.Tests
{
public static class BreakTests
{
[Theory]
[InlineData(100, 10)]
[InlineData(100, 20)]
[InlineData(1000, 100)]
[InlineData(1000, 200)]
public static void TestFor_Break_Basic(int loopsize, int breakpoint)
{
var complete = new bool[loopsize];
Parallel.For(0, loopsize, delegate(int i, ParallelLoopState ps)
{
complete[i] = true;
if (i >= breakpoint) ps.Break();
//Thread.Sleep(2);
});
// Should not be any omissions prior
// to break, and there should be some after.
for (int i = 0; i <= breakpoint; i++)
{
Assert.True(complete[i], string.Format("TestForBreak: Failed: incomplete at {0}, loopsize {1}, breakpoint {2}", i, loopsize, breakpoint));
}
bool result = true;
for (int i = breakpoint + 1; i < loopsize; i++)
{
if (!complete[i])
{
result = true;
break;
}
}
Assert.True(result, "TestForBreak: Failed: Could not detect any interruption of For-loop.");
}
[Theory]
[InlineData(100, 10)]
[InlineData(100, 20)]
[InlineData(1000, 100)]
[InlineData(1000, 200)]
public static void TestFor_Break_64Bits(int loopsize, int breakpoint)
{
var complete = new bool[loopsize];
// Throw a curveball here and loop from just-under-Int32.MaxValue to
// just-over-Int32.MaxValue. Make sure that 64-bit indices are being
// handled correctly.
long loopbase = (long)Int32.MaxValue - 10;
Parallel.For(loopbase, loopbase + loopsize, delegate(long i, ParallelLoopState ps)
{
complete[i - loopbase] = true;
if ((i - loopbase) >= breakpoint) ps.Break();
//Thread.Sleep(2);
});
// Should not be any omissions prior
// to break, and there should be some after.
for (long i = 0; i <= breakpoint; i++)
{
Assert.True(complete[i], string.Format("TestFor64Break: Failed: incomplete at {0}, loopsize {1}, breakpoint {2}", i, loopsize, breakpoint));
}
bool result = false;
for (long i = breakpoint + 1; i < loopsize; i++)
{
if (!complete[i])
{
result = true;
break;
}
}
Assert.True(result, "TestFor64Break: Failed: Could not detect any interruption of For-loop.");
}
[Theory]
[InlineData(500, 10)]
[InlineData(500, 20)]
[InlineData(1000, 100)]
[InlineData(1000, 200)]
public static void TestForEach_Break(int loopsize, int breakpoint)
{
var complete = new bool[loopsize];
// NOTE: Make sure and use some collection that is NOT a list or an
// array. Lists/arrays will be essentially be passed through
// Parallel.For() logic, which will make this test fail.
var iqueue = new Queue<int>();
for (int i = 0; i < loopsize; i++) iqueue.Enqueue(i);
Parallel.ForEach(iqueue, delegate(int i, ParallelLoopState ps)
{
complete[i] = true;
if (i >= breakpoint) ps.Break();
//Thread.Sleep(2);
});
// Same rules as For-loop. Should not be any omissions prior
// to break, and there should be some after.
for (int i = 0; i <= breakpoint; i++)
{
Assert.True(complete[i], string.Format("TestForEachBreak(loopsize={0},breakpoint={1}): Failed: incomplete at {2}", loopsize, breakpoint, i));
}
bool result = false;
for (int i = breakpoint + 1; i < loopsize; i++)
{
if (!complete[i])
{
result = true;
break;
}
}
Assert.True(result, string.Format("TestForEachBreak(loopsize={0},breakpoint={1}): Failed: Could not detect any interruption of For-loop.", loopsize, breakpoint));
//
// Now try it for OrderablePartitioner
//
var ilist = new List<int>();
for (int i = 0; i < loopsize; i++)
{
ilist.Add(i);
complete[i] = false;
}
OrderablePartitioner<int> mop = Partitioner.Create(ilist, true);
Parallel.ForEach(mop, delegate(int item, ParallelLoopState ps, long index)
{
//break does not imply that the other iterations will not be run
//http://msdn.microsoft.com/en-us/library/system.threading.tasks.parallelloopstate.break.aspx
//execute the test with high loop size and low break index
complete[index] = true;
if (index >= breakpoint) ps.Break();
//Thread.Sleep(2);
});
for (int i = 0; i <= breakpoint; i++)
{
Assert.True(complete[i], string.Format("TestForEachBreak(loopsize={0},breakpoint={1}): Failed: incomplete at {2}", loopsize, breakpoint, i));
}
result = false;
for (int i = breakpoint + 1; i < loopsize; i++)
{
if (!complete[i])
{
result = true;
break;
}
}
Assert.True(result, string.Format("TestForEachBreak(loopsize={0},breakpoint={1}): Failed: Could not detect any interruption of For-loop.", loopsize, breakpoint));
}
}
}

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<BuildConfigurations>
netstandard1.5;
</BuildConfigurations>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,47 @@
// 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.Collections.Concurrent;
using System.Diagnostics.Tracing;
using System.Linq;
using Xunit;
namespace System.Threading.Tasks.Tests
{
public static class EtwTests
{
[Fact]
public static void TestEtw()
{
using (var listener = new TestEventListener("System.Threading.Tasks.Parallel.EventSource", EventLevel.Verbose))
{
var events = new ConcurrentQueue<int>();
listener.RunWithCallback(ev => events.Enqueue(ev.EventId), () => {
Parallel.For(0, 10000, i => { });
var barrier = new Barrier(2);
Parallel.Invoke(
() => barrier.SignalAndWait(),
() => barrier.SignalAndWait());
});
const int BeginLoopEventId = 1;
const int BeginInvokeEventId = 3;
Assert.Equal(expected: 1, actual: events.Count(i => i == BeginLoopEventId));
Assert.Equal(expected: 1, actual: events.Count(i => i == BeginInvokeEventId));
const int EndLoopEventId = 2;
const int EndInvokeEventId = 4;
Assert.Equal(expected: 1, actual: events.Count(i => i == EndLoopEventId));
Assert.Equal(expected: 1, actual: events.Count(i => i == EndInvokeEventId));
const int ForkEventId = 5;
const int JoinEventId = 6;
Assert.True(events.Count(i => i == ForkEventId) >= 1);
Assert.Equal(events.Count(i => i == ForkEventId), events.Count(i => i == JoinEventId));
}
}
}
}

View File

@ -0,0 +1,77 @@
// 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 Xunit;
namespace System.Threading.Tasks.Tests
{
public static class ParallelForUnitTests
{
[Theory]
[InlineData(API.For64, StartIndexBase.Int32, 0, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For64, StartIndexBase.Int32, 10, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.For64, StartIndexBase.Int32, 10, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For64, StartIndexBase.Int32, 1, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.For64, StartIndexBase.Int32, 1, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.For64, StartIndexBase.Int32, 2, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For64, StartIndexBase.Int32, 2, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.For64, StartIndexBase.Int32, 97, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.For64, StartIndexBase.Int32, 97, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 0, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 10, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 10, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.For, StartIndexBase.Zero, 10, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 1, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 1, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.For, StartIndexBase.Zero, 2, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 2, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.For, StartIndexBase.Zero, 97, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.For, StartIndexBase.Zero, 97, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 0, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 10, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 10, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 1, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 1, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 2, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 2, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 97, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnArray, StartIndexBase.Zero, 97, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 0, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 10, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 10, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 1, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 1, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 2, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 2, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 97, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.ForeachOnList, StartIndexBase.Zero, 97, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 0, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.Foreach, StartIndexBase.Zero, 10, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 10, WithParallelOption.None, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.Foreach, StartIndexBase.Zero, 10, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 1, WithParallelOption.None, ActionWithState.None, ActionWithLocal.None)]
[InlineData(API.Foreach, StartIndexBase.Zero, 1, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 2, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 2, WithParallelOption.WithDOP, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 2, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.None)]
[InlineData(API.Foreach, StartIndexBase.Zero, 97, WithParallelOption.None, ActionWithState.None, ActionWithLocal.HasFinally)]
[InlineData(API.Foreach, StartIndexBase.Zero, 97, WithParallelOption.WithDOP, ActionWithState.Stop, ActionWithLocal.None)]
public static void ParrallelFor(API api, StartIndexBase startIndexBase, int count, WithParallelOption parallelOption, ActionWithState stateOption, ActionWithLocal localOption)
{
var parameters = new TestParameters(api, startIndexBase)
{
Count = count,
ParallelOption = parallelOption,
StateOption = stateOption,
LocalOption = localOption
};
var test = new ParallelForTest(parameters);
test.RealRun();
}
}
}

View File

@ -0,0 +1,76 @@
// 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 Xunit;
namespace System.Threading.Tasks.Tests
{
public static class ParallelForBoundaryUnitTests
{
[Theory]
[OuterLoop]
[InlineData(API.For64, StartIndexBase.Int16, -1000, 100, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int16, 0, 5, WorkloadPattern.Random)]
[InlineData(API.For64, StartIndexBase.Int16, 100, 100, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Int32, -1000, 5, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int32, 0, 5, WorkloadPattern.Decreasing)]
[InlineData(API.For64, StartIndexBase.Int32, 0, 5, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Int32, 0, 100, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int32, 0, 100, WorkloadPattern.Random)]
[InlineData(API.For64, StartIndexBase.Int32, 100, 5, WorkloadPattern.Decreasing)]
[InlineData(API.For64, StartIndexBase.Int32, 100, 5, WorkloadPattern.Random)]
[InlineData(API.For64, StartIndexBase.Int32, 100, 5, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Int32, 100, 100, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int32, 1000, 5, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int32, 1000, 5, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Int32, 1000, 100, WorkloadPattern.Decreasing)]
[InlineData(API.For64, StartIndexBase.Int32, 1000, 100, WorkloadPattern.Random)]
[InlineData(API.For64, StartIndexBase.Int64, -1000, 100, WorkloadPattern.Decreasing)]
[InlineData(API.For64, StartIndexBase.Int64, -1000, 100, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int64, -1000, 5, WorkloadPattern.Random)]
[InlineData(API.For64, StartIndexBase.Int64, -100, 5, WorkloadPattern.Decreasing)]
[InlineData(API.For64, StartIndexBase.Int64, -100, 5, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Int64, -100, 5, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Int64, -100, 100, WorkloadPattern.Random)]
[InlineData(API.For64, StartIndexBase.Int64, -100, 100, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Zero, 0, 5, WorkloadPattern.Increasing)]
[InlineData(API.For64, StartIndexBase.Zero, 0, 100, WorkloadPattern.Decreasing)]
[InlineData(API.For64, StartIndexBase.Zero, 0, 100, WorkloadPattern.Similar)]
[InlineData(API.For64, StartIndexBase.Zero, 100, 5, WorkloadPattern.Random)]
[InlineData(API.For, StartIndexBase.Int16, -100, 5, WorkloadPattern.Similar)]
[InlineData(API.For, StartIndexBase.Int16, -1000, 5, WorkloadPattern.Similar)]
[InlineData(API.For, StartIndexBase.Int16, -1000, 100, WorkloadPattern.Random)]
[InlineData(API.For, StartIndexBase.Int16, 0, 5, WorkloadPattern.Increasing)]
[InlineData(API.For, StartIndexBase.Int16, 0, 100, WorkloadPattern.Decreasing)]
[InlineData(API.For, StartIndexBase.Int16, 100, 5, WorkloadPattern.Increasing)]
[InlineData(API.For, StartIndexBase.Int16, 100, 100, WorkloadPattern.Random)]
[InlineData(API.For, StartIndexBase.Int16, 1000, 5, WorkloadPattern.Decreasing)]
[InlineData(API.For, StartIndexBase.Int16, 1000, 100, WorkloadPattern.Similar)]
[InlineData(API.For, StartIndexBase.Int32, -1000, 5, WorkloadPattern.Decreasing)]
[InlineData(API.For, StartIndexBase.Int32, -100, 5, WorkloadPattern.Random)]
[InlineData(API.For, StartIndexBase.Int32, -100, 100, WorkloadPattern.Decreasing)]
[InlineData(API.For, StartIndexBase.Int32, -1000, 100, WorkloadPattern.Similar)]
[InlineData(API.For, StartIndexBase.Zero, 0, 5, WorkloadPattern.Similar)]
[InlineData(API.For, StartIndexBase.Zero, 100, 100, WorkloadPattern.Decreasing)]
[InlineData(API.For, StartIndexBase.Zero, 100, 100, WorkloadPattern.Random)]
[InlineData(API.For, StartIndexBase.Zero, 1000, 5, WorkloadPattern.Decreasing)]
[InlineData(API.For, StartIndexBase.Zero, 1000, 5, WorkloadPattern.Random)]
public static void TestFor_Boundary(API api, StartIndexBase startIndexBase, int startIndexOffset, int count, WorkloadPattern workloadPattern)
{
var parameters = new TestParameters(api, startIndexBase, startIndexOffset)
{
Count = count,
WorkloadPattern = workloadPattern,
};
var test = new ParallelForTest(parameters);
test.RealRun();
}
}
}

Some files were not shown because too many files have changed in this diff Show More