Skip to content

Commit 902d431

Browse files
author
Oren Novotny
committed
Add in AsyncIteratorMethodBuilder to support the async iterators on downlevel platforms
1 parent ffe3aff commit 902d431

File tree

7 files changed

+103
-239
lines changed

7 files changed

+103
-239
lines changed

Ix.NET/Source/System.Interactive.Async.Providers/Reflection.cs

Lines changed: 0 additions & 117 deletions
This file was deleted.

Ix.NET/Source/System.Linq.Async.Queryable/Reflection.cs

Lines changed: 0 additions & 117 deletions
This file was deleted.

Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableQuery.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
using System.Collections.Generic;
66
using System.Linq.Expressions;
7+
using System.Reflection;
78
using System.Threading;
89
using System.Threading.Tasks;
910

Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableRewriter.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,14 @@ protected override Expression VisitParameter(ParameterExpression node)
110110

111111
private static Type GetPublicType(Type type)
112112
{
113-
if (!type.IsNestedPrivate())
113+
if (!type.GetTypeInfo().IsNestedPrivate)
114114
{
115115
return type;
116116
}
117117

118118
foreach (var ifType in type.GetInterfaces())
119119
{
120-
if (ifType.IsGenericType())
120+
if (ifType.GetTypeInfo().IsGenericType)
121121
{
122122
var def = ifType.GetGenericTypeDefinition();
123123
if (def == typeof(IAsyncEnumerable<>) || def == typeof(IAsyncGrouping<,>))
@@ -461,15 +461,15 @@ private static Type FindGenericType(Type definition, Type type)
461461
//
462462
// If the current type matches the specified definition, return.
463463
//
464-
if (type.IsGenericType() && type.GetGenericTypeDefinition() == definition)
464+
if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == definition)
465465
{
466466
return type;
467467
}
468468

469469
//
470470
// Probe all interfaces implemented by the current type.
471471
//
472-
if (definition.IsInterface())
472+
if (definition.GetTypeInfo().IsInterface)
473473
{
474474
foreach (var ifType in type.GetInterfaces())
475475
{
@@ -484,7 +484,7 @@ private static Type FindGenericType(Type definition, Type type)
484484
//
485485
// Continue up the type hierarchy.
486486
//
487-
type = type.GetBaseType();
487+
type = type.GetTypeInfo().BaseType;
488488
}
489489

490490
return null;

Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
<ItemGroup>
2121
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
22+
<PackageReference Condition="'$(TargetFramework)' == 'netstandard1.4' " Include="System.Reflection.TypeExtensions" Version="4.5.1" />
2223
<ReferenceAssemblyProjectReference Include="..\refs\System.Linq.Async.Ref\System.Linq.Async.Ref.csproj" />
2324
</ItemGroup>
2425

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#if !BCL_HAS_CONFIGUREAWAIT
2+
3+
// Licensed to the .NET Foundation under one or more agreements.
4+
// The .NET Foundation licenses this file to you under the MIT license.
5+
// See the LICENSE file in the project root for more information.
6+
7+
using System.Diagnostics;
8+
using System.Reflection;
9+
using System.Runtime.InteropServices;
10+
using System.Text;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
14+
namespace System.Runtime.CompilerServices
15+
{
16+
/// <summary>Represents a builder for asynchronous iterators.</summary>
17+
[StructLayout(LayoutKind.Auto)]
18+
public struct AsyncIteratorMethodBuilder
19+
{
20+
// AsyncIteratorMethodBuilder is used by the language compiler as part of generating
21+
// async iterators. For now, the implementation just wraps AsyncTaskMethodBuilder, as
22+
// most of the logic is shared. However, in the future this could be changed and
23+
// optimized. For example, we do need to allocate an object (once) to flow state like
24+
// ExecutionContext, which AsyncTaskMethodBuilder handles, but it handles it by
25+
// allocating a Task-derived object. We could optimize this further by removing
26+
// the Task from the hierarchy, but in doing so we'd also lose a variety of optimizations
27+
// related to it, so we'd need to replicate all of those optimizations (e.g. storing
28+
// that box object directly into a Task's continuation field).
29+
30+
#pragma warning disable IDE0044 // Add readonly modifier
31+
private AsyncTaskMethodBuilder _methodBuilder; // mutable struct; do not make it readonly
32+
#pragma warning restore IDE0044 // Add readonly modifier
33+
34+
/// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary>
35+
/// <returns>The initialized instance.</returns>
36+
public static AsyncIteratorMethodBuilder Create() =>
37+
#if PROJECTN
38+
// ProjectN's AsyncTaskMethodBuilder.Create() currently does additional debugger-related
39+
// work, so we need to delegate to it.
40+
new AsyncIteratorMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() };
41+
#else
42+
// _methodBuilder should be initialized to AsyncTaskMethodBuilder.Create(), but on coreclr
43+
// that Create() is a nop, so we can just return the default here.
44+
default;
45+
#endif
46+
47+
/// <summary>Invokes <see cref="IAsyncStateMachine.MoveNext"/> on the state machine while guarding the <see cref="ExecutionContext"/>.</summary>
48+
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
49+
/// <param name="stateMachine">The state machine instance, passed by reference.</param>
50+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
51+
public void MoveNext<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
52+
#if CORERT || !BCL_HAS_CONFIGUREAWAIT
53+
_methodBuilder.Start(ref stateMachine);
54+
#else
55+
AsyncMethodBuilderCore.Start(ref stateMachine);
56+
#endif
57+
58+
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
59+
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
60+
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
61+
/// <param name="awaiter">The awaiter.</param>
62+
/// <param name="stateMachine">The state machine.</param>
63+
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
64+
where TAwaiter : INotifyCompletion
65+
where TStateMachine : IAsyncStateMachine =>
66+
_methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
67+
68+
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
69+
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
70+
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
71+
/// <param name="awaiter">The awaiter.</param>
72+
/// <param name="stateMachine">The state machine.</param>
73+
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
74+
where TAwaiter : ICriticalNotifyCompletion
75+
where TStateMachine : IAsyncStateMachine =>
76+
_methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
77+
78+
/// <summary>Marks iteration as being completed, whether successfully or otherwise.</summary>
79+
public void Complete() => _methodBuilder.SetResult();
80+
81+
/// <summary>Gets an object that may be used to uniquely identify this builder to the debugger.</summary>
82+
internal object ObjectIdForDebugger => typeof(AsyncTaskMethodBuilder)
83+
.GetProperty("ObjectIdForDebugger", BindingFlags.Instance | BindingFlags.NonPublic)
84+
.GetMethod.Invoke(_methodBuilder, null);
85+
86+
87+
}
88+
}
89+
90+
#else
91+
using System.Runtime.CompilerServices;
92+
93+
[assembly: TypeForwardedTo(typeof(AsyncIteratorMethodBuilder))]
94+
95+
#endif

Ix.NET/Source/refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
<ItemGroup>
1212
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
13+
<PackageReference Condition="'$(TargetFramework)' == 'netstandard1.4' " Include="System.Reflection.TypeExtensions" Version="4.5.1" />
1314
</ItemGroup>
1415

1516
<ItemGroup>

0 commit comments

Comments
 (0)