You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@@ -7,6 +7,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks.Exte
|
||||
{DE90AD0B-649D-4062-B8D9-9658DE140532} = {DE90AD0B-649D-4062-B8D9-9658DE140532}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks.Extensions.Performance.Tests", "tests\Performance\System.Threading.Tasks.Extensions.Performance.Tests.csproj", "{77E38A48-61ED-4D79-9136-D88617EE3558}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{DE90AD0B-649D-4062-B8D9-9658DE140532} = {DE90AD0B-649D-4062-B8D9-9658DE140532}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Threading.Tasks.Extensions", "src\System.Threading.Tasks.Extensions.csproj", "{DE90AD0B-649D-4062-B8D9-9658DE140532}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{0DF7FA9A-E7D3-4CEF-862B-A37F5BBBB54C} = {0DF7FA9A-E7D3-4CEF-862B-A37F5BBBB54C}
|
||||
@@ -30,6 +35,10 @@ Global
|
||||
{275B161B-D525-48A0-B1DE-344273AB9A99}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
|
||||
{275B161B-D525-48A0-B1DE-344273AB9A99}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
|
||||
{275B161B-D525-48A0-B1DE-344273AB9A99}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
|
||||
{77E38A48-61ED-4D79-9136-D88617EE3558}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU
|
||||
{77E38A48-61ED-4D79-9136-D88617EE3558}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU
|
||||
{77E38A48-61ED-4D79-9136-D88617EE3558}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU
|
||||
{77E38A48-61ED-4D79-9136-D88617EE3558}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU
|
||||
{DE90AD0B-649D-4062-B8D9-9658DE140532}.Debug|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Debug|Any CPU
|
||||
{DE90AD0B-649D-4062-B8D9-9658DE140532}.Debug|Any CPU.Build.0 = netcoreapp-Windows_NT-Debug|Any CPU
|
||||
{DE90AD0B-649D-4062-B8D9-9658DE140532}.Release|Any CPU.ActiveCfg = netcoreapp-Windows_NT-Release|Any CPU
|
||||
@@ -44,6 +53,7 @@ Global
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{275B161B-D525-48A0-B1DE-344273AB9A99} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
|
||||
{77E38A48-61ED-4D79-9136-D88617EE3558} = {1A2F9F4A-A032-433E-B914-ADD5992BB178}
|
||||
{DE90AD0B-649D-4062-B8D9-9658DE140532} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD}
|
||||
{0DF7FA9A-E7D3-4CEF-862B-A37F5BBBB54C} = {2E666815-2EDB-464B-9DF6-380BF4789AD4}
|
||||
EndGlobalSection
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\dir.props" />
|
||||
<PropertyGroup>
|
||||
<AssemblyVersion>4.1.2.0</AssemblyVersion>
|
||||
<AssemblyVersion>4.2.0.0</AssemblyVersion>
|
||||
<!-- System.Threading.Tasks.Extensions has forwarded types into the runtime on netcoreapp/uap
|
||||
It must win over assemblies versioned at 4.2.* -->
|
||||
<AssemblyVersion Condition="'$(TargetGroup)' == 'netcoreapp' OR '$(TargetGroup)' == 'uap' ">4.3.0.0</AssemblyVersion>
|
||||
<AssemblyKey>Open</AssemblyKey>
|
||||
<IsNETCoreApp>true</IsNETCoreApp>
|
||||
<IsUAP>true</IsUAP>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\src\System.Threading.Tasks.Extensions.csproj" />
|
||||
|
||||
<InboxOnTargetFramework Include="netcoreapp2.0" />
|
||||
<InboxOnTargetFramework Include="netcoreapp2.1" />
|
||||
<InboxOnTargetFramework Include="$(UAPvNextTFM)" />
|
||||
|
||||
<!-- this package is part of the implementation closure of NETStandard.Library
|
||||
@@ -19,4 +19,4 @@
|
||||
<SuppressMetaPackage Include="NETStandard.Library" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -13,6 +13,18 @@ namespace System.Runtime.CompilerServices
|
||||
public AsyncMethodBuilderAttribute(System.Type builderType) { }
|
||||
public System.Type BuilderType { get { throw null; } }
|
||||
}
|
||||
public partial struct AsyncValueTaskMethodBuilder
|
||||
{
|
||||
private object _dummy;
|
||||
public System.Threading.Tasks.ValueTask Task { get { throw null; } }
|
||||
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
|
||||
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
|
||||
public static System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder Create() { throw null; }
|
||||
public void SetException(System.Exception exception) { }
|
||||
public void SetResult() { }
|
||||
public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
|
||||
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
|
||||
}
|
||||
public partial struct AsyncValueTaskMethodBuilder<TResult>
|
||||
{
|
||||
private TResult _result;
|
||||
@@ -25,22 +37,43 @@ namespace System.Runtime.CompilerServices
|
||||
public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
|
||||
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
|
||||
}
|
||||
public readonly partial struct ConfiguredValueTaskAwaitable
|
||||
{
|
||||
private readonly object _dummy;
|
||||
public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter GetAwaiter() { throw null; }
|
||||
public readonly partial struct ConfiguredValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
|
||||
{
|
||||
private readonly object _dummy;
|
||||
public bool IsCompleted { get { throw null; } }
|
||||
public void GetResult() { }
|
||||
public void OnCompleted(System.Action continuation) { }
|
||||
public void UnsafeOnCompleted(System.Action continuation) { }
|
||||
}
|
||||
}
|
||||
public readonly partial struct ConfiguredValueTaskAwaitable<TResult>
|
||||
{
|
||||
private readonly object _dummy;
|
||||
public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<TResult>.ConfiguredValueTaskAwaiter GetAwaiter() { throw null; }
|
||||
public partial struct ConfiguredValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
|
||||
public readonly partial struct ConfiguredValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
|
||||
{
|
||||
private object _dummy;
|
||||
private readonly object _dummy;
|
||||
public bool IsCompleted { get { throw null; } }
|
||||
public TResult GetResult() { throw null; }
|
||||
public void OnCompleted(System.Action continuation) { }
|
||||
public void UnsafeOnCompleted(System.Action continuation) { }
|
||||
}
|
||||
}
|
||||
public partial struct ValueTaskAwaiter<TResult> : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
|
||||
public readonly partial struct ValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
|
||||
{
|
||||
private object _dummy;
|
||||
private readonly object _dummy;
|
||||
public bool IsCompleted { get { throw null; } }
|
||||
public void GetResult() { }
|
||||
public void OnCompleted(System.Action continuation) { }
|
||||
public void UnsafeOnCompleted(System.Action continuation) { }
|
||||
}
|
||||
public readonly partial struct ValueTaskAwaiter<TResult> : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
|
||||
{
|
||||
private readonly object _dummy;
|
||||
public bool IsCompleted { get { throw null; } }
|
||||
public TResult GetResult() { throw null; }
|
||||
public void OnCompleted(System.Action continuation) { }
|
||||
@@ -49,11 +82,32 @@ namespace System.Runtime.CompilerServices
|
||||
}
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
[System.Runtime.CompilerServices.AsyncMethodBuilderAttribute(typeof(System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder))]
|
||||
public readonly partial struct ValueTask : System.IEquatable<System.Threading.Tasks.ValueTask>
|
||||
{
|
||||
internal readonly object _dummy;
|
||||
public ValueTask(System.Threading.Tasks.Task task) { throw null; }
|
||||
public ValueTask(System.Threading.Tasks.Sources.IValueTaskSource source, short token) { throw null; }
|
||||
public bool IsCanceled { get { throw null; } }
|
||||
public bool IsCompleted { get { throw null; } }
|
||||
public bool IsCompletedSuccessfully { get { throw null; } }
|
||||
public bool IsFaulted { get { throw null; } }
|
||||
public System.Threading.Tasks.Task AsTask() { throw null; }
|
||||
public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) { throw null; }
|
||||
public override bool Equals(object obj) { throw null; }
|
||||
public bool Equals(System.Threading.Tasks.ValueTask other) { throw null; }
|
||||
public System.Runtime.CompilerServices.ValueTaskAwaiter GetAwaiter() { throw null; }
|
||||
public override int GetHashCode() { throw null; }
|
||||
public System.Threading.Tasks.ValueTask Preserve() { throw null; }
|
||||
public static bool operator ==(System.Threading.Tasks.ValueTask left, System.Threading.Tasks.ValueTask right) { throw null; }
|
||||
public static bool operator !=(System.Threading.Tasks.ValueTask left, System.Threading.Tasks.ValueTask right) { throw null; }
|
||||
}
|
||||
[System.Runtime.CompilerServices.AsyncMethodBuilderAttribute(typeof(System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<>))]
|
||||
public readonly partial struct ValueTask<TResult> : System.IEquatable<System.Threading.Tasks.ValueTask<TResult>>
|
||||
{
|
||||
internal readonly TResult _result;
|
||||
public ValueTask(System.Threading.Tasks.Task<TResult> task) { throw null; }
|
||||
public ValueTask(System.Threading.Tasks.Sources.IValueTaskSource<TResult> source, short token) { throw null; }
|
||||
public ValueTask(TResult result) { throw null; }
|
||||
public bool IsCanceled { get { throw null; } }
|
||||
public bool IsCompleted { get { throw null; } }
|
||||
@@ -62,14 +116,42 @@ namespace System.Threading.Tasks
|
||||
public TResult Result { get { throw null; } }
|
||||
public System.Threading.Tasks.Task<TResult> AsTask() { throw null; }
|
||||
public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) { throw null; }
|
||||
[System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))]
|
||||
public static System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<TResult> CreateAsyncMethodBuilder() { throw null; }
|
||||
public override bool Equals(object obj) { throw null; }
|
||||
public bool Equals(System.Threading.Tasks.ValueTask<TResult> other) { throw null; }
|
||||
public System.Runtime.CompilerServices.ValueTaskAwaiter<TResult> GetAwaiter() { throw null; }
|
||||
public override int GetHashCode() { throw null; }
|
||||
public System.Threading.Tasks.ValueTask<TResult> Preserve() { throw null; }
|
||||
public static bool operator ==(System.Threading.Tasks.ValueTask<TResult> left, System.Threading.Tasks.ValueTask<TResult> right) { throw null; }
|
||||
public static bool operator !=(System.Threading.Tasks.ValueTask<TResult> left, System.Threading.Tasks.ValueTask<TResult> right) { throw null; }
|
||||
public override string ToString() { throw null; }
|
||||
}
|
||||
}
|
||||
namespace System.Threading.Tasks.Sources
|
||||
{
|
||||
[System.Flags]
|
||||
public enum ValueTaskSourceOnCompletedFlags
|
||||
{
|
||||
None,
|
||||
UseSchedulingContext = 0x1,
|
||||
FlowExecutionContext = 0x2,
|
||||
}
|
||||
public enum ValueTaskSourceStatus
|
||||
{
|
||||
Pending = 0,
|
||||
Succeeded = 1,
|
||||
Faulted = 2,
|
||||
Canceled = 3
|
||||
}
|
||||
public interface IValueTaskSource
|
||||
{
|
||||
System.Threading.Tasks.Sources.ValueTaskSourceStatus GetStatus(short token);
|
||||
void OnCompleted(System.Action<object> continuation, object state, short token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags);
|
||||
void GetResult(short token);
|
||||
}
|
||||
public interface IValueTaskSource<out TResult>
|
||||
{
|
||||
System.Threading.Tasks.Sources.ValueTaskSourceStatus GetStatus(short token);
|
||||
void OnCompleted(System.Action<object> continuation, object state, short token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags);
|
||||
TResult GetResult(short token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
<PropertyGroup>
|
||||
<ProjectGuid>{0DF7FA9A-E7D3-4CEF-862B-A37F5BBBB54C}</ProjectGuid>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' == 'netcoreapp' Or '$(TargetGroup)' == 'uap'">true</IsPartialFacadeAssembly>
|
||||
<!--
|
||||
Netstandard assembly version is frozen and thus cannot adde any more APIs to it because
|
||||
the types have been moved inbox and type-forwarded into CoreLib. The only way to add more
|
||||
APIs is to add them directly to the particular platform.
|
||||
-->
|
||||
<AssemblyVersion Condition="$(TargetGroup.StartsWith('netstandard'))">4.1.1.0</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<DocumentationFile>$(OutputPath)$(MSBuildProjectName).xml</DocumentationFile>
|
||||
<PackageTargetFramework Condition="'$(TargetGroup)' == 'netstandard1.0'">netstandard1.0;portable-net45+win8+wp8+wpa81</PackageTargetFramework>
|
||||
<IsPartialFacadeAssembly Condition="'$(TargetGroup)' != 'netstandard' and '$(TargetGroup)' != 'netstandard1.0'">true</IsPartialFacadeAssembly>
|
||||
<DefineConstants Condition="'$(IsPartialFacadeAssembly)' != 'true'">$(DefineConstants);netstandard</DefineConstants>
|
||||
<ExcludeResourcesImport Condition="'$(IsPartialFacadeAssembly)'=='true'">true</ExcludeResourcesImport>
|
||||
<AssemblyVersion Condition="$(TargetGroup.StartsWith('netstandard'))">4.1.1.0</AssemblyVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
|
||||
@@ -23,15 +23,34 @@
|
||||
<ReferenceFromRuntime Include="System.Private.CoreLib" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(IsPartialFacadeAssembly)' != 'true'">
|
||||
<Compile Include="System\Runtime\CompilerServices\AsyncMethodBuilderAttribute.cs" />
|
||||
<Compile Include="System\Runtime\CompilerServices\AsyncValueTaskMethodBuilder.cs" />
|
||||
<Compile Include="System\Runtime\CompilerServices\ConfiguredValueTaskAwaitable.cs" />
|
||||
<Compile Include="System\Runtime\CompilerServices\ValueTaskAwaiter.cs" />
|
||||
<Compile Include="System\Threading\Tasks\ValueTask.cs" />
|
||||
<Compile Include="System\ThrowHelper.cs" />
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Diagnostics\StackTraceHiddenAttribute.cs">
|
||||
<Link>Common\CoreLib\System\Diagnostics\StackTraceHiddenAttribute.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Runtime\CompilerServices\AsyncMethodBuilderAttribute.cs">
|
||||
<Link>Common\CoreLib\System\Runtime\CompilerServices\AsyncMethodBuilderAttribute.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Runtime\CompilerServices\AsyncValueTaskMethodBuilder.cs">
|
||||
<Link>Common\CoreLib\System\Runtime\CompilerServices\AsyncValueTaskMethodBuilder.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Runtime\CompilerServices\ConfiguredValueTaskAwaitable.cs">
|
||||
<Link>Common\CoreLib\System\Runtime\CompilerServices\ConfiguredValueTaskAwaitable.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Runtime\CompilerServices\ValueTaskAwaiter.cs">
|
||||
<Link>Common\CoreLib\System\Runtime\CompilerServices\ValueTaskAwaiter.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Threading\Tasks\ValueTask.cs">
|
||||
<Link>Common\CoreLib\System\Threading\Tasks\ValueTask.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonPath)\CoreLib\System\Threading\Tasks\Sources\IValueTaskSource.cs">
|
||||
<Link>Common\CoreLib\System\Threading\Tasks\Sources\IValueTaskSource.cs</Link>
|
||||
</Compile>
|
||||
|
||||
<Reference Include="System.Collections" />
|
||||
<Reference Include="System.Diagnostics.Debug" />
|
||||
<Reference Include="System.Runtime" />
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe" />
|
||||
<Reference Include="System.Threading.Tasks" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the type of the async method builder that should be used by a language compiler to
|
||||
/// build the attributed type when used as the return type of an async method.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate | AttributeTargets.Enum, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class AsyncMethodBuilderAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes the <see cref="AsyncMethodBuilderAttribute"/>.</summary>
|
||||
/// <param name="builderType">The <see cref="Type"/> of the associated builder.</param>
|
||||
public AsyncMethodBuilderAttribute(Type builderType) => BuilderType = builderType;
|
||||
|
||||
/// <summary>Gets the <see cref="Type"/> of the associated builder.</summary>
|
||||
public Type BuilderType { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
/// <summary>Represents a builder for asynchronous methods that returns a <see cref="ValueTask{TResult}"/>.</summary>
|
||||
/// <typeparam name="TResult">The type of the result.</typeparam>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public struct AsyncValueTaskMethodBuilder<TResult>
|
||||
{
|
||||
/// <summary>The <see cref="AsyncTaskMethodBuilder{TResult}"/> to which most operations are delegated.</summary>
|
||||
private AsyncTaskMethodBuilder<TResult> _methodBuilder;
|
||||
/// <summary>The result for this builder, if it's completed before any awaits occur.</summary>
|
||||
private TResult _result;
|
||||
/// <summary>true if <see cref="_result"/> contains the synchronous result for the async method; otherwise, false.</summary>
|
||||
private bool _haveResult;
|
||||
/// <summary>true if the builder should be used for setting/getting the result; otherwise, false.</summary>
|
||||
private bool _useBuilder;
|
||||
|
||||
/// <summary>Creates an instance of the <see cref="AsyncValueTaskMethodBuilder{TResult}"/> struct.</summary>
|
||||
/// <returns>The initialized instance.</returns>
|
||||
public static AsyncValueTaskMethodBuilder<TResult> Create() =>
|
||||
new AsyncValueTaskMethodBuilder<TResult>() { _methodBuilder = AsyncTaskMethodBuilder<TResult>.Create() };
|
||||
|
||||
/// <summary>Begins running the builder with the associated state machine.</summary>
|
||||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
|
||||
/// <param name="stateMachine">The state machine instance, passed by reference.</param>
|
||||
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
|
||||
_methodBuilder.Start(ref stateMachine); // will provide the right ExecutionContext semantics
|
||||
|
||||
/// <summary>Associates the builder with the specified state machine.</summary>
|
||||
/// <param name="stateMachine">The state machine instance to associate with the builder.</param>
|
||||
public void SetStateMachine(IAsyncStateMachine stateMachine) => _methodBuilder.SetStateMachine(stateMachine);
|
||||
|
||||
/// <summary>Marks the task as successfully completed.</summary>
|
||||
/// <param name="result">The result to use to complete the task.</param>
|
||||
public void SetResult(TResult result)
|
||||
{
|
||||
if (_useBuilder)
|
||||
{
|
||||
_methodBuilder.SetResult(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
_result = result;
|
||||
_haveResult = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Marks the task as failed and binds the specified exception to the task.</summary>
|
||||
/// <param name="exception">The exception to bind to the task.</param>
|
||||
public void SetException(Exception exception) => _methodBuilder.SetException(exception);
|
||||
|
||||
/// <summary>Gets the task for this builder.</summary>
|
||||
public ValueTask<TResult> Task
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_haveResult)
|
||||
{
|
||||
return new ValueTask<TResult>(_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
_useBuilder = true;
|
||||
return new ValueTask<TResult>(_methodBuilder.Task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
|
||||
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
|
||||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
|
||||
/// <param name="awaiter">the awaiter</param>
|
||||
/// <param name="stateMachine">The state machine.</param>
|
||||
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
|
||||
where TAwaiter : INotifyCompletion
|
||||
where TStateMachine : IAsyncStateMachine
|
||||
{
|
||||
_useBuilder = true;
|
||||
_methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
|
||||
}
|
||||
|
||||
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
|
||||
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
|
||||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
|
||||
/// <param name="awaiter">the awaiter</param>
|
||||
/// <param name="stateMachine">The state machine.</param>
|
||||
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
|
||||
where TAwaiter : ICriticalNotifyCompletion
|
||||
where TStateMachine : IAsyncStateMachine
|
||||
{
|
||||
_useBuilder = true;
|
||||
_methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
/// <summary>Provides an awaitable type that enables configured awaits on a <see cref="ValueTask{TResult}"/>.</summary>
|
||||
/// <typeparam name="TResult">The type of the result produced.</typeparam>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly struct ConfiguredValueTaskAwaitable<TResult>
|
||||
{
|
||||
/// <summary>The wrapped <see cref="ValueTask{TResult}"/>.</summary>
|
||||
private readonly ValueTask<TResult> _value;
|
||||
/// <summary>true to attempt to marshal the continuation back to the original context captured; otherwise, false.</summary>
|
||||
private readonly bool _continueOnCapturedContext;
|
||||
|
||||
/// <summary>Initializes the awaitable.</summary>
|
||||
/// <param name="value">The wrapped <see cref="ValueTask{TResult}"/>.</param>
|
||||
/// <param name="continueOnCapturedContext">
|
||||
/// true to attempt to marshal the continuation back to the original synchronization context captured; otherwise, false.
|
||||
/// </param>
|
||||
internal ConfiguredValueTaskAwaitable(ValueTask<TResult> value, bool continueOnCapturedContext)
|
||||
{
|
||||
_value = value;
|
||||
_continueOnCapturedContext = continueOnCapturedContext;
|
||||
}
|
||||
|
||||
/// <summary>Returns an awaiter for this <see cref="ConfiguredValueTaskAwaitable{TResult}"/> instance.</summary>
|
||||
public ConfiguredValueTaskAwaiter GetAwaiter() =>
|
||||
new ConfiguredValueTaskAwaiter(_value, _continueOnCapturedContext);
|
||||
|
||||
/// <summary>Provides an awaiter for a <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion
|
||||
{
|
||||
/// <summary>The value being awaited.</summary>
|
||||
private readonly ValueTask<TResult> _value;
|
||||
/// <summary>The value to pass to ConfigureAwait.</summary>
|
||||
private readonly bool _continueOnCapturedContext;
|
||||
|
||||
/// <summary>Initializes the awaiter.</summary>
|
||||
/// <param name="value">The value to be awaited.</param>
|
||||
/// <param name="continueOnCapturedContext">The value to pass to ConfigureAwait.</param>
|
||||
internal ConfiguredValueTaskAwaiter(ValueTask<TResult> value, bool continueOnCapturedContext)
|
||||
{
|
||||
_value = value;
|
||||
_continueOnCapturedContext = continueOnCapturedContext;
|
||||
}
|
||||
|
||||
/// <summary>Gets whether the <see cref="ConfiguredValueTaskAwaitable{TResult}"/> has completed.</summary>
|
||||
public bool IsCompleted => _value.IsCompleted;
|
||||
|
||||
/// <summary>Gets the result of the ValueTask.</summary>
|
||||
public TResult GetResult() =>
|
||||
_value._task == null ?
|
||||
_value._result :
|
||||
_value._task.GetAwaiter().GetResult();
|
||||
|
||||
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
|
||||
public void OnCompleted(Action continuation) =>
|
||||
_value.AsTask().ConfigureAwait(_continueOnCapturedContext).GetAwaiter().OnCompleted(continuation);
|
||||
|
||||
/// <summary>Schedules the continuation action for the <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
|
||||
public void UnsafeOnCompleted(Action continuation) =>
|
||||
_value.AsTask().ConfigureAwait(_continueOnCapturedContext).GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
/// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary>
|
||||
public readonly struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion
|
||||
{
|
||||
/// <summary>The value being awaited.</summary>
|
||||
private readonly ValueTask<TResult> _value;
|
||||
|
||||
/// <summary>Initializes the awaiter.</summary>
|
||||
/// <param name="value">The value to be awaited.</param>
|
||||
internal ValueTaskAwaiter(ValueTask<TResult> value) => _value = value;
|
||||
|
||||
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> has completed.</summary>
|
||||
public bool IsCompleted => _value.IsCompleted;
|
||||
|
||||
/// <summary>Gets the result of the ValueTask.</summary>
|
||||
public TResult GetResult() =>
|
||||
_value._task == null ?
|
||||
_value._result :
|
||||
_value._task.GetAwaiter().GetResult();
|
||||
|
||||
/// <summary>Schedules the continuation action for this ValueTask.</summary>
|
||||
public void OnCompleted(Action continuation) =>
|
||||
_value.AsTask().ConfigureAwait(continueOnCapturedContext: true).GetAwaiter().OnCompleted(continuation);
|
||||
|
||||
/// <summary>Schedules the continuation action for this ValueTask.</summary>
|
||||
public void UnsafeOnCompleted(Action continuation) =>
|
||||
_value.AsTask().ConfigureAwait(continueOnCapturedContext: true).GetAwaiter().UnsafeOnCompleted(continuation);
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
#if !MONO
|
||||
using System.ComponentModel;
|
||||
#endif
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a value type that wraps a <see cref="Task{TResult}"/> and a <typeparamref name="TResult"/>,
|
||||
/// only one of which is used.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the result.</typeparam>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Methods may return an instance of this value type when it's likely that the result of their
|
||||
/// operations will be available synchronously and when the method is expected to be invoked so
|
||||
/// frequently that the cost of allocating a new <see cref="Task{TResult}"/> for each call will
|
||||
/// be prohibitive.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// There are tradeoffs to using a <see cref="ValueTask{TResult}"/> instead of a <see cref="Task{TResult}"/>.
|
||||
/// For example, while a <see cref="ValueTask{TResult}"/> can help avoid an allocation in the case where the
|
||||
/// successful result is available synchronously, it also contains two fields whereas a <see cref="Task{TResult}"/>
|
||||
/// as a reference type is a single field. This means that a method call ends up returning two fields worth of
|
||||
/// data instead of one, which is more data to copy. It also means that if a method that returns one of these
|
||||
/// is awaited within an async method, the state machine for that async method will be larger due to needing
|
||||
/// to store the struct that's two fields instead of a single reference.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Further, for uses other than consuming the result of an asynchronous operation via await,
|
||||
/// <see cref="ValueTask{TResult}"/> can lead to a more convoluted programming model, which can in turn actually
|
||||
/// lead to more allocations. For example, consider a method that could return either a <see cref="Task{TResult}"/>
|
||||
/// with a cached task as a common result or a <see cref="ValueTask{TResult}"/>. If the consumer of the result
|
||||
/// wants to use it as a <see cref="Task{TResult}"/>, such as to use with in methods like Task.WhenAll and Task.WhenAny,
|
||||
/// the <see cref="ValueTask{TResult}"/> would first need to be converted into a <see cref="Task{TResult}"/> using
|
||||
/// <see cref="ValueTask{TResult}.AsTask"/>, which leads to an allocation that would have been avoided if a cached
|
||||
/// <see cref="Task{TResult}"/> had been used in the first place.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// As such, the default choice for any asynchronous method should be to return a <see cref="Task"/> or
|
||||
/// <see cref="Task{TResult}"/>. Only if performance analysis proves it worthwhile should a <see cref="ValueTask{TResult}"/>
|
||||
/// be used instead of <see cref="Task{TResult}"/>. There is no non-generic version of <see cref="ValueTask{TResult}"/>
|
||||
/// as the Task.CompletedTask property may be used to hand back a successfully completed singleton in the case where
|
||||
/// a <see cref="Task"/>-returning method completes synchronously and successfully.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
|
||||
[StructLayout(LayoutKind.Auto)]
|
||||
public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
|
||||
{
|
||||
/// <summary>The task to be used if the operation completed asynchronously or if it completed synchronously but non-successfully.</summary>
|
||||
internal readonly Task<TResult> _task;
|
||||
/// <summary>The result to be used if the operation completed successfully synchronously.</summary>
|
||||
internal readonly TResult _result;
|
||||
|
||||
/// <summary>Initialize the <see cref="ValueTask{TResult}"/> with the result of the successful operation.</summary>
|
||||
/// <param name="result">The result.</param>
|
||||
public ValueTask(TResult result)
|
||||
{
|
||||
_task = null;
|
||||
_result = result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the <see cref="ValueTask{TResult}"/> with a <see cref="Task{TResult}"/> that represents the operation.
|
||||
/// </summary>
|
||||
/// <param name="task">The task.</param>
|
||||
public ValueTask(Task<TResult> task)
|
||||
{
|
||||
_task = task ?? throw new ArgumentNullException(nameof(task));
|
||||
_result = default(TResult);
|
||||
}
|
||||
|
||||
/// <summary>Returns the hash code for this instance.</summary>
|
||||
public override int GetHashCode() =>
|
||||
_task != null ? _task.GetHashCode() :
|
||||
_result != null ? _result.GetHashCode() :
|
||||
0;
|
||||
|
||||
/// <summary>Returns a value indicating whether this value is equal to a specified <see cref="object"/>.</summary>
|
||||
public override bool Equals(object obj) =>
|
||||
obj is ValueTask<TResult> &&
|
||||
Equals((ValueTask<TResult>)obj);
|
||||
|
||||
/// <summary>Returns a value indicating whether this value is equal to a specified <see cref="ValueTask{TResult}"/> value.</summary>
|
||||
public bool Equals(ValueTask<TResult> other) =>
|
||||
_task != null || other._task != null ?
|
||||
_task == other._task :
|
||||
EqualityComparer<TResult>.Default.Equals(_result, other._result);
|
||||
|
||||
/// <summary>Returns a value indicating whether two <see cref="ValueTask{TResult}"/> values are equal.</summary>
|
||||
public static bool operator==(ValueTask<TResult> left, ValueTask<TResult> right) =>
|
||||
left.Equals(right);
|
||||
|
||||
/// <summary>Returns a value indicating whether two <see cref="ValueTask{TResult}"/> values are not equal.</summary>
|
||||
public static bool operator!=(ValueTask<TResult> left, ValueTask<TResult> right) =>
|
||||
!left.Equals(right);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Task{TResult}"/> object to represent this ValueTask. It will
|
||||
/// either return the wrapped task object if one exists, or it'll manufacture a new
|
||||
/// task object to represent the result.
|
||||
/// </summary>
|
||||
public Task<TResult> AsTask() =>
|
||||
// Return the task if we were constructed from one, otherwise manufacture one. We don't
|
||||
// cache the generated task into _task as it would end up changing both equality comparison
|
||||
// and the hash code we generate in GetHashCode.
|
||||
_task ?? Task.FromResult(_result);
|
||||
|
||||
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a completed operation.</summary>
|
||||
public bool IsCompleted => _task == null || _task.IsCompleted;
|
||||
|
||||
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a successfully completed operation.</summary>
|
||||
public bool IsCompletedSuccessfully => _task == null || _task.Status == TaskStatus.RanToCompletion;
|
||||
|
||||
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a failed operation.</summary>
|
||||
public bool IsFaulted => _task != null && _task.IsFaulted;
|
||||
|
||||
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a canceled operation.</summary>
|
||||
public bool IsCanceled => _task != null && _task.IsCanceled;
|
||||
|
||||
/// <summary>Gets the result.</summary>
|
||||
public TResult Result => _task == null ? _result : _task.GetAwaiter().GetResult();
|
||||
|
||||
/// <summary>Gets an awaiter for this value.</summary>
|
||||
public ValueTaskAwaiter<TResult> GetAwaiter() => new ValueTaskAwaiter<TResult>(this);
|
||||
|
||||
/// <summary>Configures an awaiter for this value.</summary>
|
||||
/// <param name="continueOnCapturedContext">
|
||||
/// true to attempt to marshal the continuation back to the captured context; otherwise, false.
|
||||
/// </param>
|
||||
public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) =>
|
||||
new ConfiguredValueTaskAwaitable<TResult>(this, continueOnCapturedContext: continueOnCapturedContext);
|
||||
|
||||
/// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
|
||||
public override string ToString()
|
||||
{
|
||||
if (_task != null)
|
||||
{
|
||||
return _task.Status == TaskStatus.RanToCompletion && _task.Result != null ?
|
||||
_task.Result.ToString() :
|
||||
string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
return _result != null ?
|
||||
_result.ToString() :
|
||||
string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove CreateAsyncMethodBuilder once the C# compiler relies on the AsyncBuilder attribute.
|
||||
|
||||
/// <summary>Creates a method builder for use with an async method.</summary>
|
||||
/// <returns>The created builder.</returns>
|
||||
#if !MONO
|
||||
[EditorBrowsable(EditorBrowsableState.Never)] // intended only for compiler consumption
|
||||
#endif
|
||||
public static AsyncValueTaskMethodBuilder<TResult> CreateAsyncMethodBuilder() => AsyncValueTaskMethodBuilder<TResult>.Create();
|
||||
}
|
||||
}
|
||||
40
external/corefx/src/System.Threading.Tasks.Extensions/src/System/ThrowHelper.cs
vendored
Normal file
40
external/corefx/src/System.Threading.Tasks.Extensions/src/System/ThrowHelper.cs
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
// 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.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class ThrowHelper
|
||||
{
|
||||
internal static void ThrowArgumentNullException(ExceptionArgument argument) =>
|
||||
throw GetArgumentNullException(argument);
|
||||
|
||||
internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) =>
|
||||
throw GetArgumentOutOfRangeException(argument);
|
||||
|
||||
private static ArgumentNullException GetArgumentNullException(ExceptionArgument argument) =>
|
||||
new ArgumentNullException(GetArgumentName(argument));
|
||||
|
||||
private static ArgumentOutOfRangeException GetArgumentOutOfRangeException(ExceptionArgument argument) =>
|
||||
new ArgumentOutOfRangeException(GetArgumentName(argument));
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static string GetArgumentName(ExceptionArgument argument)
|
||||
{
|
||||
Debug.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument),
|
||||
$"The enum value is not defined, please check the {nameof(ExceptionArgument)} enum.");
|
||||
|
||||
return argument.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
internal enum ExceptionArgument
|
||||
{
|
||||
task,
|
||||
source,
|
||||
state
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace System.Runtime.CompilerServices.Tests
|
||||
[Theory]
|
||||
[InlineData(typeof(string))]
|
||||
[InlineData(typeof(int))]
|
||||
[InlineData(typeof(AsyncValueTaskMethodBuilder))]
|
||||
[InlineData(typeof(AsyncValueTaskMethodBuilder<>))]
|
||||
[InlineData(typeof(AsyncValueTaskMethodBuilder<int>))]
|
||||
[InlineData(typeof(AsyncValueTaskMethodBuilder<string>))]
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// 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.Runtime.CompilerServices;
|
||||
using Xunit;
|
||||
|
||||
@@ -11,16 +10,32 @@ namespace System.Threading.Tasks.Tests
|
||||
public class AsyncValueTaskMethodBuilderTests
|
||||
{
|
||||
[Fact]
|
||||
public void Create_ReturnsDefaultInstance()
|
||||
public void NonGeneric_Create_ReturnsDefaultInstance()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
Assert.Equal(default(AsyncValueTaskMethodBuilder<int>), b); // implementation detail being verified
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
Assert.Equal(default, b); // implementation detail being verified
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetResult_BeforeAccessTask_ValueTaskContainsValue()
|
||||
public void Generic_Create_ReturnsDefaultInstance()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
Assert.Equal(default, b); // implementation detail being verified
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NonGeneric_SetResult_BeforeAccessTask_ValueTaskIsDefault()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
b.SetResult();
|
||||
ValueTask vt = b.Task;
|
||||
Assert.True(vt == default);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_SetResult_BeforeAccessTask_ValueTaskContainsValue()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
b.SetResult(42);
|
||||
ValueTask<int> vt = b.Task;
|
||||
Assert.True(vt.IsCompletedSuccessfully);
|
||||
@@ -29,9 +44,20 @@ namespace System.Threading.Tasks.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetResult_AfterAccessTask_ValueTaskContainsValue()
|
||||
public void NonGeneric_SetResult_AfterAccessTask_ValueTaskContainsValue()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
ValueTask vt = b.Task;
|
||||
b.SetResult();
|
||||
Assert.False(vt == default);
|
||||
Assert.True(vt.IsCompletedSuccessfully);
|
||||
Assert.True(WrapsTask(vt));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_SetResult_AfterAccessTask_ValueTaskContainsValue()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
ValueTask<int> vt = b.Task;
|
||||
b.SetResult(42);
|
||||
Assert.True(vt.IsCompletedSuccessfully);
|
||||
@@ -40,9 +66,20 @@ namespace System.Threading.Tasks.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetException_BeforeAccessTask_FaultsTask()
|
||||
public void NonGeneric_SetException_BeforeAccessTask_FaultsTask()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
var e = new FormatException();
|
||||
b.SetException(e);
|
||||
ValueTask vt = b.Task;
|
||||
Assert.True(vt.IsFaulted);
|
||||
Assert.Same(e, Assert.Throws<FormatException>(() => vt.GetAwaiter().GetResult()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_SetException_BeforeAccessTask_FaultsTask()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
var e = new FormatException();
|
||||
b.SetException(e);
|
||||
ValueTask<int> vt = b.Task;
|
||||
@@ -51,9 +88,20 @@ namespace System.Threading.Tasks.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetException_AfterAccessTask_FaultsTask()
|
||||
public void NonGeneric_SetException_AfterAccessTask_FaultsTask()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
var e = new FormatException();
|
||||
ValueTask vt = b.Task;
|
||||
b.SetException(e);
|
||||
Assert.True(vt.IsFaulted);
|
||||
Assert.Same(e, Assert.Throws<FormatException>(() => vt.GetAwaiter().GetResult()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_SetException_AfterAccessTask_FaultsTask()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
var e = new FormatException();
|
||||
ValueTask<int> vt = b.Task;
|
||||
b.SetException(e);
|
||||
@@ -62,9 +110,20 @@ namespace System.Threading.Tasks.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetException_OperationCanceledException_CancelsTask()
|
||||
public void NonGeneric_SetException_OperationCanceledException_CancelsTask()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
var e = new OperationCanceledException();
|
||||
ValueTask vt = b.Task;
|
||||
b.SetException(e);
|
||||
Assert.True(vt.IsCanceled);
|
||||
Assert.Same(e, Assert.Throws<OperationCanceledException>(() => vt.GetAwaiter().GetResult()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_SetException_OperationCanceledException_CancelsTask()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
var e = new OperationCanceledException();
|
||||
ValueTask<int> vt = b.Task;
|
||||
b.SetException(e);
|
||||
@@ -73,9 +132,19 @@ namespace System.Threading.Tasks.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Start_InvokesMoveNext()
|
||||
public void NonGeneric_Start_InvokesMoveNext()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
int invokes = 0;
|
||||
var dsm = new DelegateStateMachine { MoveNextDelegate = () => invokes++ };
|
||||
b.Start(ref dsm);
|
||||
Assert.Equal(1, invokes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_Start_InvokesMoveNext()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
int invokes = 0;
|
||||
var dsm = new DelegateStateMachine { MoveNextDelegate = () => invokes++ };
|
||||
b.Start(ref dsm);
|
||||
@@ -87,9 +156,40 @@ namespace System.Threading.Tasks.Tests
|
||||
[InlineData(2, false)]
|
||||
[InlineData(1, true)]
|
||||
[InlineData(2, true)]
|
||||
public void AwaitOnCompleted_ForcesTaskCreation(int numAwaits, bool awaitUnsafe)
|
||||
public void NonGeneric_AwaitOnCompleted_ForcesTaskCreation(int numAwaits, bool awaitUnsafe)
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
|
||||
var dsm = new DelegateStateMachine();
|
||||
TaskAwaiter<int> t = new TaskCompletionSource<int>().Task.GetAwaiter();
|
||||
|
||||
Assert.InRange(numAwaits, 1, int.MaxValue);
|
||||
for (int i = 1; i <= numAwaits; i++)
|
||||
{
|
||||
if (awaitUnsafe)
|
||||
{
|
||||
b.AwaitUnsafeOnCompleted(ref t, ref dsm);
|
||||
}
|
||||
else
|
||||
{
|
||||
b.AwaitOnCompleted(ref t, ref dsm);
|
||||
}
|
||||
}
|
||||
|
||||
b.SetResult();
|
||||
|
||||
Assert.True(WrapsTask(b.Task));
|
||||
Assert.True(b.Task.IsCompletedSuccessfully);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(1, false)]
|
||||
[InlineData(2, false)]
|
||||
[InlineData(1, true)]
|
||||
[InlineData(2, true)]
|
||||
public void Generic_AwaitOnCompleted_ForcesTaskCreation(int numAwaits, bool awaitUnsafe)
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
|
||||
var dsm = new DelegateStateMachine();
|
||||
TaskAwaiter<int> t = new TaskCompletionSource<int>().Task.GetAwaiter();
|
||||
@@ -115,14 +215,22 @@ namespace System.Threading.Tasks.Tests
|
||||
|
||||
[Fact]
|
||||
[ActiveIssue("https://github.com/dotnet/corefx/issues/22506", TargetFrameworkMonikers.UapAot)]
|
||||
public void SetStateMachine_InvalidArgument_ThrowsException()
|
||||
public void NonGeneric_SetStateMachine_InvalidArgument_ThrowsException()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
AssertExtensions.Throws<ArgumentNullException>("stateMachine", () => b.SetStateMachine(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Start_ExecutionContextChangesInMoveNextDontFlowOut()
|
||||
[ActiveIssue("https://github.com/dotnet/corefx/issues/22506", TargetFrameworkMonikers.UapAot)]
|
||||
public void Generic_SetStateMachine_InvalidArgument_ThrowsException()
|
||||
{
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
AssertExtensions.Throws<ArgumentNullException>("stateMachine", () => b.SetStateMachine(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NonGeneric_Start_ExecutionContextChangesInMoveNextDontFlowOut()
|
||||
{
|
||||
var al = new AsyncLocal<int> { Value = 0 };
|
||||
int calls = 0;
|
||||
@@ -144,7 +252,41 @@ namespace System.Threading.Tasks.Tests
|
||||
Assert.Equal(2, al.Value);
|
||||
Assert.Equal(2, calls);
|
||||
|
||||
AsyncValueTaskMethodBuilder<int> b = ValueTask<int>.CreateAsyncMethodBuilder();
|
||||
AsyncValueTaskMethodBuilder b = default;
|
||||
b.Start(ref dsm);
|
||||
Assert.Equal(2, al.Value); // change should not be visible
|
||||
Assert.Equal(3, calls);
|
||||
|
||||
// Make sure we've not caused the Task to be allocated
|
||||
b.SetResult();
|
||||
ValueTask vt = b.Task;
|
||||
Assert.False(WrapsTask(vt));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Generic_Start_ExecutionContextChangesInMoveNextDontFlowOut()
|
||||
{
|
||||
var al = new AsyncLocal<int> { Value = 0 };
|
||||
int calls = 0;
|
||||
|
||||
var dsm = new DelegateStateMachine
|
||||
{
|
||||
MoveNextDelegate = () =>
|
||||
{
|
||||
al.Value++;
|
||||
calls++;
|
||||
}
|
||||
};
|
||||
|
||||
dsm.MoveNext();
|
||||
Assert.Equal(1, al.Value);
|
||||
Assert.Equal(1, calls);
|
||||
|
||||
dsm.MoveNext();
|
||||
Assert.Equal(2, al.Value);
|
||||
Assert.Equal(2, calls);
|
||||
|
||||
AsyncValueTaskMethodBuilder<int> b = default;
|
||||
b.Start(ref dsm);
|
||||
Assert.Equal(2, al.Value); // change should not be visible
|
||||
Assert.Equal(3, calls);
|
||||
@@ -160,7 +302,25 @@ namespace System.Threading.Tasks.Tests
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
[InlineData(10)]
|
||||
public static async Task UsedWithAsyncMethod_CompletesSuccessfully(int yields)
|
||||
public static async Task NonGeneric_UsedWithAsyncMethod_CompletesSuccessfully(int yields)
|
||||
{
|
||||
await ValueTaskReturningAsyncMethod(42);
|
||||
|
||||
ValueTask vt = ValueTaskReturningAsyncMethod(84);
|
||||
Assert.Equal(yields > 0, WrapsTask(vt));
|
||||
|
||||
async ValueTask ValueTaskReturningAsyncMethod(int result)
|
||||
{
|
||||
for (int i = 0; i < yields; i++) await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)]
|
||||
[InlineData(1)]
|
||||
[InlineData(2)]
|
||||
[InlineData(10)]
|
||||
public static async Task Generic_UsedWithAsyncMethod_CompletesSuccessfully(int yields)
|
||||
{
|
||||
Assert.Equal(42, await ValueTaskReturningAsyncMethod(42));
|
||||
|
||||
@@ -175,7 +335,129 @@ namespace System.Threading.Tasks.Tests
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets whether the ValueTask has a non-null Task.</summary>
|
||||
[Fact]
|
||||
public static async Task AwaitTasksAndValueTasks_InTaskAndValueTaskMethods()
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
await TaskReturningMethod();
|
||||
Assert.Equal(17, await TaskInt32ReturningMethod());
|
||||
await ValueTaskReturningMethod();
|
||||
Assert.Equal(18, await ValueTaskInt32ReturningMethod());
|
||||
}
|
||||
|
||||
async Task TaskReturningMethod()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// Complete
|
||||
await Task.CompletedTask;
|
||||
await Task.FromResult(42);
|
||||
await new ValueTask();
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(42));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.FromResult(42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Completed(42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
|
||||
// Incomplete
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.Delay(1).ContinueWith(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.Delay(1).ContinueWith(_ => 42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.Delay(1).ContinueWith<int>(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
async Task<int> TaskInt32ReturningMethod()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// Complete
|
||||
await Task.CompletedTask;
|
||||
await Task.FromResult(42);
|
||||
await new ValueTask();
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(42));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.FromResult(42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Completed(42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
|
||||
// Incomplete
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.Delay(1).ContinueWith(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.Delay(1).ContinueWith(_ => 42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.Delay(1).ContinueWith<int>(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
await Task.Yield();
|
||||
}
|
||||
return 17;
|
||||
}
|
||||
|
||||
async ValueTask ValueTaskReturningMethod()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// Complete
|
||||
await Task.CompletedTask;
|
||||
await Task.FromResult(42);
|
||||
await new ValueTask();
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(42));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.FromResult(42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Completed(42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
|
||||
// Incomplete
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.Delay(1).ContinueWith(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.Delay(1).ContinueWith(_ => 42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.Delay(1).ContinueWith<int>(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
await Task.Yield();
|
||||
}
|
||||
}
|
||||
|
||||
async ValueTask<int> ValueTaskInt32ReturningMethod()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// Complete
|
||||
await Task.CompletedTask;
|
||||
await Task.FromResult(42);
|
||||
await new ValueTask();
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(42));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.FromResult(42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Completed(42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.FromException<int>(new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Completed(0, new FormatException()), 0));
|
||||
|
||||
// Incomplete
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(Task.Delay(1).ContinueWith(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
Assert.Equal(42, await new ValueTask<int>(Task.Delay(1).ContinueWith(_ => 42)));
|
||||
Assert.Equal(42, await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 42, null), 0));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(Task.Delay(1).ContinueWith<int>(_ => throw new FormatException())));
|
||||
await Assert.ThrowsAsync<FormatException>(async () => await new ValueTask<int>(ManualResetValueTaskSource.Delay(1, 0, new FormatException()), 0));
|
||||
await Task.Yield();
|
||||
}
|
||||
return 18;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool WrapsTask(ValueTask vt) => vt != default;
|
||||
private static bool WrapsTask<T>(ValueTask<T> vt) => ReferenceEquals(vt.AsTask(), vt.AsTask());
|
||||
|
||||
private struct DelegateStateMachine : IAsyncStateMachine
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<BuildConfigurations>
|
||||
netcoreapp;
|
||||
uap;
|
||||
netfx;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
8
external/corefx/src/System.Threading.Tasks.Extensions/tests/Performance/Configurations.props
vendored
Normal file
8
external/corefx/src/System.Threading.Tasks.Extensions/tests/Performance/Configurations.props
vendored
Normal 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>
|
||||
259
external/corefx/src/System.Threading.Tasks.Extensions/tests/Performance/Perf.ValueTask.cs
vendored
Normal file
259
external/corefx/src/System.Threading.Tasks.Extensions/tests/Performance/Perf.ValueTask.cs
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
// 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.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks.Sources;
|
||||
using System.Threading.Tasks.Tests;
|
||||
using Microsoft.Xunit.Performance;
|
||||
using Xunit;
|
||||
|
||||
namespace System.Threading.Tasks
|
||||
{
|
||||
public class ValueTaskPerfTest
|
||||
{
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task Await_FromResult()
|
||||
{
|
||||
ValueTask<int> vt = new ValueTask<int>(42);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await vt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task Await_FromCompletedTask()
|
||||
{
|
||||
ValueTask<int> vt = new ValueTask<int>(Task.FromResult(42));
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await vt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task Await_FromCompletedValueTaskSource()
|
||||
{
|
||||
ValueTask<int> vt = new ValueTask<int>(ManualResetValueTaskSource.Completed<int>(42), 0);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await vt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromResult()
|
||||
{
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>((int)i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromResult_ConfigureAwait()
|
||||
{
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>((int)i).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromCompletedTask()
|
||||
{
|
||||
Task<int> t = Task.FromResult(42);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromCompletedTask_ConfigureAwait()
|
||||
{
|
||||
Task<int> t = Task.FromResult(42);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>(t).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromCompletedValueTaskSource()
|
||||
{
|
||||
IValueTaskSource<int> vts = ManualResetValueTaskSource.Completed(42);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>(vts, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromCompletedValueTaskSource_ConfigureAwait()
|
||||
{
|
||||
IValueTaskSource<int> vts = ManualResetValueTaskSource.Completed(42);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>(vts, 0).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromYieldingAsyncMethod()
|
||||
{
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
await new ValueTask<int>(YieldOnce());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 1_000_000), MeasureGCAllocations]
|
||||
public async Task CreateAndAwait_FromDelayedTCS()
|
||||
{
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<int>();
|
||||
ValueTask<int> vt = AwaitTcsAsValueTask(tcs);
|
||||
tcs.SetResult(42);
|
||||
await vt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public void Copy_PassAsArgumentAndReturn_FromResult()
|
||||
{
|
||||
ValueTask<int> vt = new ValueTask<int>(42);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
vt = ReturnValueTask(vt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public void Copy_PassAsArgumentAndReturn_FromTask()
|
||||
{
|
||||
ValueTask<int> vt = new ValueTask<int>(Task.FromResult(42));
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
vt = ReturnValueTask(vt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Benchmark(InnerIterationCount = 10_000_000), MeasureGCAllocations]
|
||||
public void Copy_PassAsArgumentAndReturn_FromValueTaskSource()
|
||||
{
|
||||
ValueTask<int> vt = new ValueTask<int>(ManualResetValueTaskSource.Completed(42), 0);
|
||||
foreach (BenchmarkIteration iteration in Benchmark.Iterations)
|
||||
{
|
||||
long iters = Benchmark.InnerIterationCount;
|
||||
using (iteration.StartMeasurement())
|
||||
{
|
||||
for (long i = 0; i < iters; i++)
|
||||
{
|
||||
vt = ReturnValueTask(vt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static ValueTask<int> ReturnValueTask(ValueTask<int> vt) => vt;
|
||||
|
||||
private async ValueTask<int> AwaitTcsAsValueTask(TaskCompletionSource<int> tcs) => await new ValueTask<int>(tcs.Task).ConfigureAwait(false);
|
||||
|
||||
private async Task<int> YieldOnce() { await Task.Yield(); return 42; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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>
|
||||
<IncludePerformanceTests>true</IncludePerformanceTests>
|
||||
<ProjectGuid>{77E38A48-61ED-4D79-9136-D88617EE3558}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
|
||||
<!-- Default configurations to help VS understand the configurations -->
|
||||
<ItemGroup>
|
||||
<Compile Include="Perf.ValueTask.cs" />
|
||||
<Compile Include="$(CommonTestPath)\System\PerfUtils.cs">
|
||||
<Link>Common\System\PerfUtils.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="$(CommonTestPath)\System\Threading\Tasks\Sources\ManualResetValueTaskSource.cs">
|
||||
<Link>Common\System\Threading\Tasks\Sources\ManualResetValueTaskSource.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(CommonPath)\..\perf\PerfRunner\PerfRunner.csproj">
|
||||
<Project>{69e46a6f-9966-45a5-8945-2559fe337827}</Project>
|
||||
<Name>PerfRunner</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
@@ -6,12 +6,20 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
|
||||
<ItemGroup>
|
||||
<Compile Include="AsyncMethodBuilderAttributeTests.cs" />
|
||||
<Compile Include="AsyncValueTaskMethodBuilderTests.cs" />
|
||||
<Compile Include="ValueTaskTests.cs" />
|
||||
<Compile Include="$(CommonTestPath)\System\Threading\Tasks\Sources\ManualResetValueTaskSource.cs">
|
||||
<Link>Common\System\Threading\Tasks\Sources\ManualResetValueTaskSource.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
</ItemGroup>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user