#if NET20 || NET30 || NET35 || NET40 || !NET_4_6
// 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
{
/// Represents a builder for asynchronous methods that returns a .
/// The type of the result.
[StructLayout(LayoutKind.Auto)]
public struct AsyncValueTaskMethodBuilder
{
/// The to which most operations are delegated.
private AsyncTaskMethodBuilder _methodBuilder;
/// The result for this builder, if it's completed before any awaits occur.
private TResult _result;
/// true if contains the synchronous result for the async method; otherwise, false.
private bool _haveResult;
/// true if the builder should be used for setting/getting the result; otherwise, false.
private bool _useBuilder;
/// Creates an instance of the struct.
/// The initialized instance.
public static AsyncValueTaskMethodBuilder Create()
{
return new AsyncValueTaskMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() };
}
/// Begins running the builder with the associated state machine.
/// The type of the state machine.
/// The state machine instance, passed by reference.
public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
{
_methodBuilder.Start(ref stateMachine); // will provide the right ExecutionContext semantics
}
/// Associates the builder with the specified state machine.
/// The state machine instance to associate with the builder.
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
_methodBuilder.SetStateMachine(stateMachine);
}
/// Marks the task as successfully completed.
/// The result to use to complete the task.
public void SetResult(TResult result)
{
if (_useBuilder)
{
_methodBuilder.SetResult(result);
}
else
{
_result = result;
_haveResult = true;
}
}
/// Marks the task as failed and binds the specified exception to the task.
/// The exception to bind to the task.
public void SetException(Exception exception)
{
_methodBuilder.SetException(exception);
}
/// Gets the task for this builder.
public ValueTask Task
{
get
{
if (_haveResult)
{
return new ValueTask(_result);
}
else
{
_useBuilder = true;
return new ValueTask(_methodBuilder.Task);
}
}
}
/// Schedules the state machine to proceed to the next action when the specified awaiter completes.
/// The type of the awaiter.
/// The type of the state machine.
/// the awaiter
/// The state machine.
public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
_useBuilder = true;
_methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
}
/// Schedules the state machine to proceed to the next action when the specified awaiter completes.
/// The type of the awaiter.
/// The type of the state machine.
/// the awaiter
/// The state machine.
[SecuritySafeCritical]
public void AwaitUnsafeOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
_useBuilder = true;
_methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
}
}
}
#endif