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
;
6 using System
.Threading
;
8 namespace System
.Runtime
.CompilerServices
10 /// <summary>Represents a builder for asynchronous iterators.</summary>
11 [StructLayout(LayoutKind
.Auto
)]
12 public struct AsyncIteratorMethodBuilder
14 // AsyncIteratorMethodBuilder is used by the language compiler as part of generating
15 // async iterators. For now, the implementation just wraps AsyncTaskMethodBuilder, as
16 // most of the logic is shared. However, in the future this could be changed and
17 // optimized. For example, we do need to allocate an object (once) to flow state like
18 // ExecutionContext, which AsyncTaskMethodBuilder handles, but it handles it by
19 // allocating a Task-derived object. We could optimize this further by removing
20 // the Task from the hierarchy, but in doing so we'd also lose a variety of optimizations
21 // related to it, so we'd need to replicate all of those optimizations (e.g. storing
22 // that box object directly into a Task's continuation field).
24 private AsyncTaskMethodBuilder _methodBuilder
; // mutable struct; do not make it readonly
26 /// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary>
27 /// <returns>The initialized instance.</returns>
28 public static AsyncIteratorMethodBuilder
Create() =>
29 // _methodBuilder should be initialized to AsyncTaskMethodBuilder.Create(), but on coreclr
30 // that Create() is a nop, so we can just return the default here.
33 /// <summary>Invokes <see cref="IAsyncStateMachine.MoveNext"/> on the state machine while guarding the <see cref="ExecutionContext"/>.</summary>
34 /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
35 /// <param name="stateMachine">The state machine instance, passed by reference.</param>
36 [MethodImpl(MethodImplOptions
.AggressiveInlining
)]
37 public void MoveNext
<TStateMachine
>(ref TStateMachine stateMachine
) where TStateMachine
: IAsyncStateMachine
=>
38 AsyncMethodBuilderCore
.Start(ref stateMachine
);
40 /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
41 /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
42 /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
43 /// <param name="awaiter">The awaiter.</param>
44 /// <param name="stateMachine">The state machine.</param>
45 public void AwaitOnCompleted
<TAwaiter
, TStateMachine
>(ref TAwaiter awaiter
, ref TStateMachine stateMachine
)
46 where TAwaiter
: INotifyCompletion
47 where TStateMachine
: IAsyncStateMachine
=>
48 _methodBuilder
.AwaitOnCompleted(ref awaiter
, ref stateMachine
);
50 /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
51 /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
52 /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
53 /// <param name="awaiter">The awaiter.</param>
54 /// <param name="stateMachine">The state machine.</param>
55 public void AwaitUnsafeOnCompleted
<TAwaiter
, TStateMachine
>(ref TAwaiter awaiter
, ref TStateMachine stateMachine
)
56 where TAwaiter
: ICriticalNotifyCompletion
57 where TStateMachine
: IAsyncStateMachine
=>
58 _methodBuilder
.AwaitUnsafeOnCompleted(ref awaiter
, ref stateMachine
);
60 /// <summary>Marks iteration as being completed, whether successfully or otherwise.</summary>
61 public void Complete() => _methodBuilder
.SetResult();
63 /// <summary>Gets an object that may be used to uniquely identify this builder to the debugger.</summary>
64 internal object ObjectIdForDebugger
=> _methodBuilder
.ObjectIdForDebugger
;