Преглед на файлове

Add in AsyncIteratorMethodBuilder to support the async iterators on downlevel platforms

Oren Novotny преди 6 години
родител
ревизия
902d43149d

+ 0 - 117
Ix.NET/Source/System.Interactive.Async.Providers/Reflection.cs

@@ -1,117 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-
-#if CRIPPLED_REFLECTION
-
-using System.Linq;
-using System.Reflection;
-
-namespace System.Reflection
-{
-    [Flags]
-    internal enum BindingFlags
-    {
-        Instance = 4,
-        Static = 8,
-        Public = 16,
-        NonPublic = 32,
-    }
-}
-
-namespace System
-{
-    internal static class TypeExtensions
-    {
-        public static bool IsNestedPrivate(this Type t)
-        {
-            return t.GetTypeInfo().IsNestedPrivate;
-        }
-
-        public static bool IsInterface(this Type t)
-        {
-            return t.GetTypeInfo().IsInterface;
-        }
-
-        public static bool IsGenericType(this Type t)
-        {
-            return t.GetTypeInfo().IsGenericType;
-        }
-
-        public static Type GetBaseType(this Type t)
-        {
-            return t.GetTypeInfo().BaseType;
-        }
-
-        public static Type[] GetGenericArguments(this Type t)
-        {
-            // TODO: check what's the right way to support this
-            return t.GetTypeInfo().GenericTypeParameters.ToArray();
-        }
-
-        public static Type[] GetInterfaces(this Type t)
-        {
-            return t.GetTypeInfo().ImplementedInterfaces.ToArray();
-        }
-
-        public static bool IsAssignableFrom(this Type t1, Type t2)
-        {
-            return t1.GetTypeInfo().IsAssignableFrom(t2.GetTypeInfo());
-        }
-
-        public static MethodInfo[] GetMethods(this Type t, BindingFlags flags)
-        {
-            return t.GetTypeInfo().DeclaredMethods.Where(m => IsVisible(m, flags)).ToArray();
-        }
-
-        private static bool IsVisible(MethodInfo method, BindingFlags flags)
-        {
-            if ((flags & BindingFlags.Public) != 0 != method.IsPublic)
-            {
-                return false;
-            }
-
-            if ((flags & BindingFlags.NonPublic) == 0 && !method.IsPublic)
-            {
-                return false;
-            }
-
-            if ((flags & BindingFlags.Static) != 0 != method.IsStatic)
-            {
-                return false;
-            }
-
-            return true;
-        }
-    }
-}
-
-#else
-
-namespace System
-{
-    internal static class TypeExtensions
-    {
-        public static bool IsNestedPrivate(this Type t)
-        {
-            return t.IsNestedPrivate;
-        }
-
-        public static bool IsInterface(this Type t)
-        {
-            return t.IsInterface;
-        }
-
-        public static bool IsGenericType(this Type t)
-        {
-            return t.IsGenericType;
-        }
-
-        public static Type GetBaseType(this Type t)
-        {
-            return t.BaseType;
-        }
-    }
-}
-
-#endif

+ 0 - 117
Ix.NET/Source/System.Linq.Async.Queryable/Reflection.cs

@@ -1,117 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License.
-// See the LICENSE file in the project root for more information. 
-
-#if CRIPPLED_REFLECTION
-
-using System.Linq;
-using System.Reflection;
-
-namespace System.Reflection
-{
-    [Flags]
-    internal enum BindingFlags
-    {
-        Instance = 4,
-        Static = 8,
-        Public = 16,
-        NonPublic = 32,
-    }
-}
-
-namespace System
-{
-    internal static class TypeExtensions
-    {
-        public static bool IsNestedPrivate(this Type t)
-        {
-            return t.GetTypeInfo().IsNestedPrivate;
-        }
-
-        public static bool IsInterface(this Type t)
-        {
-            return t.GetTypeInfo().IsInterface;
-        }
-
-        public static bool IsGenericType(this Type t)
-        {
-            return t.GetTypeInfo().IsGenericType;
-        }
-
-        public static Type GetBaseType(this Type t)
-        {
-            return t.GetTypeInfo().BaseType;
-        }
-
-        public static Type[] GetGenericArguments(this Type t)
-        {
-            // TODO: check what's the right way to support this
-            return t.GetTypeInfo().GenericTypeParameters.ToArray();
-        }
-
-        public static Type[] GetInterfaces(this Type t)
-        {
-            return t.GetTypeInfo().ImplementedInterfaces.ToArray();
-        }
-
-        public static bool IsAssignableFrom(this Type t1, Type t2)
-        {
-            return t1.GetTypeInfo().IsAssignableFrom(t2.GetTypeInfo());
-        }
-
-        public static MethodInfo[] GetMethods(this Type t, BindingFlags flags)
-        {
-            return t.GetTypeInfo().DeclaredMethods.Where(m => IsVisible(m, flags)).ToArray();
-        }
-
-        private static bool IsVisible(MethodInfo method, BindingFlags flags)
-        {
-            if ((flags & BindingFlags.Public) != 0 != method.IsPublic)
-            {
-                return false;
-            }
-
-            if ((flags & BindingFlags.NonPublic) == 0 && !method.IsPublic)
-            {
-                return false;
-            }
-
-            if ((flags & BindingFlags.Static) != 0 != method.IsStatic)
-            {
-                return false;
-            }
-
-            return true;
-        }
-    }
-}
-
-#else
-
-namespace System
-{
-    internal static class TypeExtensions
-    {
-        public static bool IsNestedPrivate(this Type t)
-        {
-            return t.IsNestedPrivate;
-        }
-
-        public static bool IsInterface(this Type t)
-        {
-            return t.IsInterface;
-        }
-
-        public static bool IsGenericType(this Type t)
-        {
-            return t.IsGenericType;
-        }
-
-        public static Type GetBaseType(this Type t)
-        {
-            return t.BaseType;
-        }
-    }
-}
-
-#endif

+ 1 - 0
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableQuery.cs

@@ -4,6 +4,7 @@
 
 using System.Collections.Generic;
 using System.Linq.Expressions;
+using System.Reflection;
 using System.Threading;
 using System.Threading.Tasks;
 

+ 5 - 5
Ix.NET/Source/System.Linq.Async.Queryable/System/Linq/AsyncEnumerableRewriter.cs

@@ -110,14 +110,14 @@ namespace System.Linq
 
         private static Type GetPublicType(Type type)
         {
-            if (!type.IsNestedPrivate())
+            if (!type.GetTypeInfo().IsNestedPrivate)
             {
                 return type;
             }
 
             foreach (var ifType in type.GetInterfaces())
             {
-                if (ifType.IsGenericType())
+                if (ifType.GetTypeInfo().IsGenericType)
                 {
                     var def = ifType.GetGenericTypeDefinition();
                     if (def == typeof(IAsyncEnumerable<>) || def == typeof(IAsyncGrouping<,>))
@@ -461,7 +461,7 @@ namespace System.Linq
                 //
                 // If the current type matches the specified definition, return.
                 //
-                if (type.IsGenericType() && type.GetGenericTypeDefinition() == definition)
+                if (type.GetTypeInfo().IsGenericType && type.GetGenericTypeDefinition() == definition)
                 {
                     return type;
                 }
@@ -469,7 +469,7 @@ namespace System.Linq
                 //
                 // Probe all interfaces implemented by the current type.
                 //
-                if (definition.IsInterface())
+                if (definition.GetTypeInfo().IsInterface)
                 {
                     foreach (var ifType in type.GetInterfaces())
                     {
@@ -484,7 +484,7 @@ namespace System.Linq
                 //
                 // Continue up the type hierarchy.
                 //
-                type = type.GetBaseType();
+                type = type.GetTypeInfo().BaseType;
             }
 
             return null;

+ 1 - 0
Ix.NET/Source/System.Linq.Async/System.Linq.Async.csproj

@@ -19,6 +19,7 @@
 
   <ItemGroup>
     <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
+    <PackageReference Condition="'$(TargetFramework)' == 'netstandard1.4' " Include="System.Reflection.TypeExtensions" Version="4.5.1" />
     <ReferenceAssemblyProjectReference Include="..\refs\System.Linq.Async.Ref\System.Linq.Async.Ref.csproj" />
   </ItemGroup>
 

+ 95 - 0
Ix.NET/Source/System.Linq.Async/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs

@@ -0,0 +1,95 @@
+#if !BCL_HAS_CONFIGUREAWAIT
+
+// 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.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Runtime.CompilerServices
+{
+    /// <summary>Represents a builder for asynchronous iterators.</summary>
+    [StructLayout(LayoutKind.Auto)]
+    public struct AsyncIteratorMethodBuilder
+    {
+        // AsyncIteratorMethodBuilder is used by the language compiler as part of generating
+        // async iterators. For now, the implementation just wraps AsyncTaskMethodBuilder, as
+        // most of the logic is shared.  However, in the future this could be changed and
+        // optimized.  For example, we do need to allocate an object (once) to flow state like
+        // ExecutionContext, which AsyncTaskMethodBuilder handles, but it handles it by
+        // allocating a Task-derived object.  We could optimize this further by removing
+        // the Task from the hierarchy, but in doing so we'd also lose a variety of optimizations
+        // related to it, so we'd need to replicate all of those optimizations (e.g. storing
+        // that box object directly into a Task's continuation field).
+
+#pragma warning disable IDE0044 // Add readonly modifier
+        private AsyncTaskMethodBuilder _methodBuilder; // mutable struct; do not make it readonly
+#pragma warning restore IDE0044 // Add readonly modifier
+
+        /// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary>
+        /// <returns>The initialized instance.</returns>
+        public static AsyncIteratorMethodBuilder Create() =>
+#if PROJECTN
+            // ProjectN's AsyncTaskMethodBuilder.Create() currently does additional debugger-related
+            // work, so we need to delegate to it.
+            new AsyncIteratorMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() };
+#else
+            // _methodBuilder should be initialized to AsyncTaskMethodBuilder.Create(), but on coreclr
+            // that Create() is a nop, so we can just return the default here.
+            default;
+#endif
+
+        /// <summary>Invokes <see cref="IAsyncStateMachine.MoveNext"/> on the state machine while guarding the <see cref="ExecutionContext"/>.</summary>
+        /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
+        /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public void MoveNext<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine =>
+#if CORERT || !BCL_HAS_CONFIGUREAWAIT
+            _methodBuilder.Start(ref stateMachine);
+#else
+            AsyncMethodBuilderCore.Start(ref stateMachine);
+#endif
+
+        /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
+        /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
+        /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
+        /// <param name="awaiter">The awaiter.</param>
+        /// <param name="stateMachine">The state machine.</param>
+        public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : INotifyCompletion
+            where TStateMachine : IAsyncStateMachine =>
+            _methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine);
+
+        /// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary>
+        /// <typeparam name="TAwaiter">The type of the awaiter.</typeparam>
+        /// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
+        /// <param name="awaiter">The awaiter.</param>
+        /// <param name="stateMachine">The state machine.</param>
+        public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
+            where TAwaiter : ICriticalNotifyCompletion
+            where TStateMachine : IAsyncStateMachine =>
+            _methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
+
+        /// <summary>Marks iteration as being completed, whether successfully or otherwise.</summary>
+        public void Complete() => _methodBuilder.SetResult();
+
+        /// <summary>Gets an object that may be used to uniquely identify this builder to the debugger.</summary>
+        internal object ObjectIdForDebugger =>  typeof(AsyncTaskMethodBuilder)
+            .GetProperty("ObjectIdForDebugger", BindingFlags.Instance | BindingFlags.NonPublic)
+            .GetMethod.Invoke(_methodBuilder, null);
+
+
+    }
+}
+
+#else
+using System.Runtime.CompilerServices;
+
+[assembly: TypeForwardedTo(typeof(AsyncIteratorMethodBuilder))]
+
+#endif

+ 1 - 0
Ix.NET/Source/refs/System.Linq.Async.Ref/System.Linq.Async.Ref.csproj

@@ -10,6 +10,7 @@
 
   <ItemGroup>
     <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.2" />
+    <PackageReference Condition="'$(TargetFramework)' == 'netstandard1.4' " Include="System.Reflection.TypeExtensions" Version="4.5.1" />
   </ItemGroup>
 
   <ItemGroup>