summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs12
-rw-r--r--src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs4
-rw-r--r--src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs51
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs4
4 files changed, 40 insertions, 31 deletions
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
index 4e8ce691be..f22b9d94bf 100644
--- a/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
@@ -35,10 +35,10 @@ namespace System.Runtime.CompilerServices
/// <summary>Provides an awaiter for a <see cref="ConfiguredValueTaskAwaitable{TResult}"/>.</summary>
[StructLayout(LayoutKind.Auto)]
- public struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, IConfiguredValueTaskAwaiter
+ public readonly struct ConfiguredValueTaskAwaiter : ICriticalNotifyCompletion, IConfiguredValueTaskAwaiter
{
/// <summary>The value being awaited.</summary>
- private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies
+ private readonly ValueTask<TResult> _value;
/// <summary>The value to pass to ConfigureAwait.</summary>
internal readonly bool _continueOnCapturedContext;
@@ -74,7 +74,11 @@ namespace System.Runtime.CompilerServices
/// <summary>Gets the task underlying the incomplete <see cref="_value"/>.</summary>
/// <remarks>This method is used when awaiting and IsCompleted returned false; thus we expect the value task to be wrapping a non-null task.</remarks>
- (Task task, bool continueOnCapturedContext) IConfiguredValueTaskAwaiter.GetTask() => (_value.AsTaskExpectNonNull(), _continueOnCapturedContext);
+ Task IConfiguredValueTaskAwaiter.GetTask(out bool continueOnCapturedContext)
+ {
+ continueOnCapturedContext = _continueOnCapturedContext;
+ return _value.AsTaskExpectNonNull();
+ }
}
}
@@ -83,6 +87,6 @@ namespace System.Runtime.CompilerServices
/// </summary>
internal interface IConfiguredValueTaskAwaiter
{
- (Task task, bool continueOnCapturedContext) GetTask();
+ Task GetTask(out bool continueOnCapturedContext);
}
}
diff --git a/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs b/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
index 7bc8b5cc7d..3f212d8bf9 100644
--- a/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
+++ b/src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
@@ -8,10 +8,10 @@ using System.Threading.Tasks;
namespace System.Runtime.CompilerServices
{
/// <summary>Provides an awaiter for a <see cref="ValueTask{TResult}"/>.</summary>
- public struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion, IValueTaskAwaiter
+ public readonly struct ValueTaskAwaiter<TResult> : ICriticalNotifyCompletion, IValueTaskAwaiter
{
/// <summary>The value being awaited.</summary>
- private ValueTask<TResult> _value; // Methods are called on this; avoid making it readonly so as to avoid unnecessary copies
+ private readonly ValueTask<TResult> _value;
/// <summary>Initializes the awaiter.</summary>
/// <param name="value">The value to be awaited.</param>
diff --git a/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs b/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs
index de9b016328..5edd8501b0 100644
--- a/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs
+++ b/src/mscorlib/shared/System/Threading/Tasks/ValueTask.cs
@@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
-using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -77,7 +76,7 @@ namespace System.Threading.Tasks
}
_task = task;
- _result = default(TResult);
+ _result = default;
}
/// <summary>Returns the hash code for this instance.</summary>
@@ -114,7 +113,12 @@ namespace System.Threading.Tasks
// 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 ?? AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
+ _task ??
+#if netstandard
+ Task.FromResult(_result);
+#else
+ AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
+#endif
internal Task<TResult> AsTaskExpectNonNull() =>
// Return the task if we were constructed from one, otherwise manufacture one.
@@ -123,13 +127,24 @@ namespace System.Threading.Tasks
_task ?? GetTaskForResultNoInlining();
[MethodImpl(MethodImplOptions.NoInlining)]
- private Task<TResult> GetTaskForResultNoInlining() => AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
+ private Task<TResult> GetTaskForResultNoInlining() =>
+#if netstandard
+ Task.FromResult(_result);
+#else
+ AsyncTaskMethodBuilder<TResult>.GetTaskForResult(_result);
+#endif
/// <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.IsCompletedSuccessfully;
+ public bool IsCompletedSuccessfully =>
+ _task == null ||
+#if netstandard
+ _task.Status == TaskStatus.RanToCompletion;
+#else
+ _task.IsCompletedSuccessfully;
+#endif
/// <summary>Gets whether the <see cref="ValueTask{TResult}"/> represents a failed operation.</summary>
public bool IsFaulted => _task != null && _task.IsFaulted;
@@ -153,26 +168,16 @@ namespace System.Threading.Tasks
/// <summary>Gets a string-representation of this <see cref="ValueTask{TResult}"/>.</summary>
public override string ToString()
{
- if (_task != null)
+ if (IsCompletedSuccessfully)
{
- return _task.IsCompletedSuccessfully && _task.Result != null ?
- _task.Result.ToString() :
- string.Empty;
+ TResult result = Result;
+ if (result != null)
+ {
+ return result.ToString();
+ }
}
- else
- {
- return _result != null ?
- _result.ToString() :
- string.Empty;
- }
- }
- // TODO https://github.com/dotnet/corefx/issues/22171:
- // 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>
- [EditorBrowsable(EditorBrowsableState.Never)] // intended only for compiler consumption
- public static AsyncValueTaskMethodBuilder<TResult> CreateAsyncMethodBuilder() => AsyncValueTaskMethodBuilder<TResult>.Create();
+ return string.Empty;
+ }
}
}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
index 30734048c5..022f15ab11 100644
--- a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
@@ -413,8 +413,8 @@ namespace System.Runtime.CompilerServices
}
else if ((null != (object)default(TAwaiter)) && (awaiter is IConfiguredValueTaskAwaiter))
{
- (Task task, bool continueOnCapturedContext) t = ((IConfiguredValueTaskAwaiter)awaiter).GetTask();
- TaskAwaiter.UnsafeOnCompletedInternal(t.task, box, t.continueOnCapturedContext);
+ Task t = ((IConfiguredValueTaskAwaiter)awaiter).GetTask(out bool continueOnCapturedContext);
+ TaskAwaiter.UnsafeOnCompletedInternal(t, box, continueOnCapturedContext);
}
// The awaiter isn't specially known. Fall back to doing a normal await.
else