ValueTask
using System.Diagnostics;
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 : IEquatable<ValueTask>
{
private sealed class ValueTaskSourceAsTask : TaskCompletionSource<bool>
{
private static readonly Action<object> s_completionAction = delegate(object state) {
ValueTaskSourceAsTask valueTaskSourceAsTask;
IValueTaskSource 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 {
source.GetResult(valueTaskSourceAsTask._token);
valueTaskSourceAsTask.TrySetResult(false);
} catch (Exception exception) {
if (status == ValueTaskSourceStatus.Canceled)
valueTaskSourceAsTask.TrySetCanceled();
else
valueTaskSourceAsTask.TrySetException(exception);
}
}
};
private IValueTaskSource _source;
private readonly short _token;
public ValueTaskSourceAsTask(IValueTaskSource source, short token)
{
_token = token;
_source = source;
source.OnCompleted(s_completionAction, this, token, ValueTaskSourceOnCompletedFlags.None);
}
}
private static readonly Task s_canceledTask = Task.Delay(-1, new CancellationToken(true));
internal readonly object _obj;
internal readonly short _token;
internal readonly bool _continueOnCapturedContext;
internal static Task CompletedTask { get; } = Task.Delay(0);
public bool IsCompleted {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
object obj = _obj;
if (obj == null)
return true;
Task task;
if ((task = (obj as Task)) != null)
return task.IsCompleted;
return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) != ValueTaskSourceStatus.Pending;
}
}
public bool IsCompletedSuccessfully {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get {
object obj = _obj;
if (obj == null)
return true;
Task task;
if ((task = (obj as Task)) != null)
return task.Status == TaskStatus.RanToCompletion;
return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Succeeded;
}
}
public bool IsFaulted {
get {
object obj = _obj;
if (obj == null)
return false;
Task task;
if ((task = (obj as Task)) != null)
return task.IsFaulted;
return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Faulted;
}
}
public bool IsCanceled {
get {
object obj = _obj;
if (obj == null)
return false;
Task task;
if ((task = (obj as Task)) != null)
return task.IsCanceled;
return Unsafe.As<IValueTaskSource>(obj).GetStatus(_token) == ValueTaskSourceStatus.Canceled;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask(Task task)
{
if (task == null)
System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.task);
_obj = task;
_continueOnCapturedContext = true;
_token = 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ValueTask(IValueTaskSource source, short token)
{
if (source == null)
System.ThrowHelper.ThrowArgumentNullException(System.ExceptionArgument.source);
_obj = source;
_token = token;
_continueOnCapturedContext = true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ValueTask(object obj, short token, bool continueOnCapturedContext)
{
_obj = obj;
_token = token;
_continueOnCapturedContext = continueOnCapturedContext;
}
public override int GetHashCode()
{
return _obj?.GetHashCode() ?? 0;
}
public override bool Equals(object obj)
{
if (obj is ValueTask)
return Equals((ValueTask)obj);
return false;
}
public bool Equals(ValueTask other)
{
if (_obj == other._obj)
return _token == other._token;
return false;
}
public static bool operator ==(ValueTask left, ValueTask right)
{
return left.Equals(right);
}
public static bool operator !=(ValueTask left, ValueTask right)
{
return !left.Equals(right);
}
public Task AsTask()
{
object obj = _obj;
object obj2;
if (obj != null) {
obj2 = (obj as Task);
if (obj2 == null)
return GetTaskForValueTaskSource(Unsafe.As<IValueTaskSource>(obj));
} else
obj2 = CompletedTask;
return (Task)obj2;
}
public ValueTask Preserve()
{
if (_obj != null)
return new ValueTask(AsTask());
return this;
}
private Task GetTaskForValueTaskSource(IValueTaskSource t)
{
ValueTaskSourceStatus status = t.GetStatus(_token);
if (status != 0)
try {
t.GetResult(_token);
return CompletedTask;
} catch (Exception exception) {
if (status != ValueTaskSourceStatus.Canceled) {
TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
taskCompletionSource.TrySetException(exception);
return taskCompletionSource.Task;
}
return s_canceledTask;
}
ValueTaskSourceAsTask valueTaskSourceAsTask = new ValueTaskSourceAsTask(t, _token);
return valueTaskSourceAsTask.Task;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[System.Diagnostics.StackTraceHidden]
internal void ThrowIfCompletedUnsuccessfully()
{
object obj = _obj;
if (obj != null) {
Task task;
if ((task = (obj as Task)) != null)
task.GetAwaiter().GetResult();
else
Unsafe.As<IValueTaskSource>(obj).GetResult(_token);
}
}
public ValueTaskAwaiter GetAwaiter()
{
return new ValueTaskAwaiter(this);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ConfiguredValueTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
{
return new ConfiguredValueTaskAwaitable(new ValueTask(_obj, _token, continueOnCapturedContext));
}
}
}