1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Runtime.InteropServices;
7 using System.Threading.Tasks;
9 namespace System.Runtime.CompilerServices
11 /// <summary>Represents a builder for asynchronous methods that returns a <see cref="ValueTask{TResult}"/>.</summary>
12 /// <typeparam name="TResult">The type of the result.</typeparam>
13 [StructLayout(LayoutKind.Auto)]
14 public struct AsyncValueTaskMethodBuilder<TResult>
16 /// <summary>The <see cref="AsyncTaskMethodBuilder{TResult}"/> to which most operations are delegated.</summary>
17 private AsyncTaskMethodBuilder<TResult> _methodBuilder; // mutable struct; do not make it readonly
18 /// <summary>The result for this builder, if it's completed before any awaits occur.</summary>
19 private TResult _result;
20 /// <summary>true if <see cref="_result"/> contains the synchronous result for the async method; otherwise, false.</summary>
21 private bool _haveResult;
22 /// <summary>true if the builder should be used for setting/getting the result; otherwise, false.</summary>
23 private bool _useBuilder;
25 /// <summary>Creates an instance of the <see cref="AsyncValueTaskMethodBuilder{TResult}"/> struct.</summary>
26 /// <returns>The initialized instance.</returns>
27 public static AsyncValueTaskMethodBuilder<TResult> Create() =>
29 // corert's AsyncTaskMethodBuilder<TResult>.Create() currently does additional debugger-related
30 // work, so we need to delegate to it.
31 new AsyncValueTaskMethodBuilder<TResult>() { _methodBuilder = AsyncTaskMethodBuilder<TResult>.Create() };
33 // _methodBuilder should be initialized to AsyncTaskMethodBuilder<TResult>.Create(), but on coreclr
34 // that Create() is a nop, so we can just return the default here.
35 default(AsyncValueTaskMethodBuilder<TResult>);
38 /// <summary>Begins running the builder with the associated state machine.</summary>
39 /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
40 /// <param name="stateMachine">The state machine instance, passed by reference.</param>
41 [MethodImpl(MethodImplOptions.AggressiveInlining)]
42 public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
43 AsyncMethodBuilder.Start(ref stateMachine); // will provide the right ExecutionContext semantics
45 /// <summary>Associates the builder with the specified state machine.</summary>
46 /// <param name="stateMachine">The state machine instance to associate with the builder.</param>
47 public void SetStateMachine(IAsyncStateMachine stateMachine) => _methodBuilder.SetStateMachine(stateMachine);
49 /// <summary>Marks the task as successfully completed.</summary>
50 /// <param name="result">The result to use to complete the task.</param>
51 public void SetResult(TResult result)
55 _methodBuilder.SetResult(result);
64 /// <summary>Marks the task as failed and binds the specified exception to the task.</summary>
65 /// <param name="exception">The exception to bind to the task.</param>
66 public void SetException(Exception exception) => _methodBuilder.SetException(exception);
68 /// <summary>Gets the task for this builder.</summary>
69 public ValueTask<TResult> Task
75 return new ValueTask<TResult>(_result);
80 return new ValueTask<TResult>(_methodBuilder.Task);
85 /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
86 /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
87 /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
88 /// <param name="awaiter">the awaiter</param>
89 /// <param name="stateMachine">The state machine.</param>
90 public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
91 where TAwaiter : INotifyCompletion
92 where TStateMachine : IAsyncStateMachine
95 _methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
98 /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
99 /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
100 /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
101 /// <param name="awaiter">the awaiter</param>
102 /// <param name="stateMachine">The state machine.</param>
103 [SecuritySafeCritical]
104 public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
105 where TAwaiter : ICriticalNotifyCompletion
106 where TStateMachine : IAsyncStateMachine
109 _methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);