ValueTask<TResult>
Provides a value type that wraps a sk{TResult} and a TResultTResult, only one of which is used.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks.Sources;
namespace System.Threading.Tasks
{
[StructLayout(LayoutKind.Auto)]
[AsyncMethodBuilder(typeof(AsyncValueTaskMethodBuilder<>))]
public readonly struct ValueTask<TResult> : IEquatable<ValueTask<TResult>>
{
private sealed class ValueTaskSourceAsTask : TaskCompletionSource<TResult>
{
private static readonly Action<object> s_completionAction = delegate(object state) {
ValueTaskSourceAsTask valueTaskSourceAsTask;
IValueTaskSource<TResult> source;
if ((valueTaskSourceAsTask = (state as ValueTaskSourceAsTask)) == null || (source = valueTaskSourceAsTask._source) == null)
System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.state);
else {
valueTaskSourceAsTask._source = null;
ValueTaskSourceStatus status = source.GetStatus(valueTaskSourceAsTask._token);
try {
valueTaskSourceAsTask.TrySetResult(source.GetResult(valueTaskSourceAsTask._token));
} catch (Exception exception) {
if (status == ValueTaskSourceStatus.Canceled)
valueTaskSourceAsTask.TrySetCanceled();
else
valueTaskSourceAsTask.TrySetException(exception);
}
}
};
private IValueTaskSource<TResult> _source;
private readonly short _token;
public ValueTaskSourceAsTask(IValueTaskSource<TResult> source, short token)
{
_source = source;
_token = token;
source.OnCompleted(s_completionAction, this, token, ValueTaskSourceOnCompletedFlags.None);
}
}
private static Task<TResult> s_canceledTask;
internal readonly object _obj;
internal readonly TResult _result;
internal readonly short _token;
internal readonly bool _continueOnCapturedContext;
public bool IsCompleted {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
object obj = _obj;
if (obj == null)
return true;
Task<TResult> task;
if ((task = (obj as Task<TResult>)) != null)
return task.IsCompleted;
return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending;
}
}
public bool IsCompletedSuccessfully {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
object obj = _obj;
if (obj == null)
return true;
Task<TResult> task;
if ((task = (obj as Task<TResult>)) != null)
return task.Status == TaskStatus.RanToCompletion;
return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded;
}
}
public bool IsFaulted {
get {
object obj = _obj;
if (obj == null)
return false;
Task<TResult> task;
if ((task = (obj as Task<TResult>)) != null)
return task.IsFaulted;
return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted;
}
}
public bool IsCanceled {
get {
object obj = _obj;
if (obj == null)
return false;
Task<TResult> task;
if ((task = (obj as Task<TResult>)) != null)
return task.IsCanceled;
return Unsafe.As<IValueTaskSource<TResult>>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled;
}
}
public TResult Result {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
object obj = _obj;
if (obj == null)
return _result;
Task<TResult> task;
if ((task = (obj as Task<TResult>)) != null)
return task.GetAwaiter().GetResult();
return Unsafe.As<IValueTaskSource<TResult>>(obj).GetResult(_token);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask(TResult result)
{
_result = result;
_obj = null;
_continueOnCapturedContext = true;
_token = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask(Task<TResult> task)
{
if (task == null)
System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.task);
_obj = task;
_result = default(TResult);
_continueOnCapturedContext = true;
_token = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask(IValueTaskSource<TResult> source, short token)
{
if (source == null)
System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.source);
_obj = source;
_token = token;
_result = default(TResult);
_continueOnCapturedContext = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ValueTask(object obj, TResult result, short token, bool continueOnCapturedContext)
{
_obj = obj;
_result = result;
_token = token;
_continueOnCapturedContext = continueOnCapturedContext;
}
public override int GetHashCode()
{
if (_obj == null) {
if (_result == null)
return 0;
return _result.GetHashCode();
}
return _obj.GetHashCode();
}
public override bool Equals(object obj)
{
if (obj is ValueTask<TResult>)
return Equals((ValueTask<TResult>)obj);
return false;
}
public bool Equals(ValueTask<TResult> other)
{
if (_obj == null && other._obj == null)
return EqualityComparer<TResult>.Default.Equals(_result, other._result);
if (_obj == other._obj)
return _token == other._token;
return false;
}
public static bool operator ==(ValueTask<TResult> left, ValueTask<TResult> right)
{
return left.Equals(right);
}
public static bool operator !=(ValueTask<TResult> left, ValueTask<TResult> right)
{
return !left.Equals(right);
}
public Task<TResult> AsTask()
{
object obj = _obj;
if (obj == null)
return Task.FromResult<TResult>(_result);
Task<TResult> result;
if ((result = (obj as Task<TResult>)) != null)
return result;
return GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource<TResult>>(obj));
}
public ValueTask<TResult> Preserve()
{
if (_obj != null)
return new ValueTask<TResult>(AsTask());
return this;
}
private Task<TResult> GetTaskForValueTaskSource(IValueTaskSource<TResult> t)
{
ValueTaskSourceStatus status = t.GetStatus(_token);
if (status != 0)
try {
return Task.FromResult<TResult>(t.GetResult(_token));
} catch (Exception exception) {
if (status != ValueTaskSourceStatus.Canceled) {
TaskCompletionSource<TResult> taskCompletionSource = new TaskCompletionSource<TResult>();
taskCompletionSource.TrySetException(exception);
return taskCompletionSource.Task;
}
Task<TResult> task = s_canceledTask;
if (task == null) {
TaskCompletionSource<TResult> taskCompletionSource2 = new TaskCompletionSource<TResult>();
taskCompletionSource2.TrySetCanceled();
task = (s_canceledTask = taskCompletionSource2.Task);
}
return task;
}
ValueTaskSourceAsTask valueTaskSourceAsTask = new ValueTaskSourceAsTask(t, _token);
return valueTaskSourceAsTask.Task;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTaskAwaiter<TResult> GetAwaiter()
{
return new ValueTaskAwaiter<TResult>(this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ConfiguredValueTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext)
{
return new ConfiguredValueTaskAwaitable<TResult>(new ValueTask<TResult>(_obj, _result, _token, continueOnCapturedContext));
}
public override string ToString()
{
if (IsCompletedSuccessfully) {
TResult result = Result;
if (result != null)
return result.ToString();
}
return string.Empty;
}
}
}