Browse Source

Adding AsyncEnumerableEx.

Bart De Smet 8 years ago
parent
commit
0bf919fd74

+ 1 - 1
Ix.NET/Source/System.Interactive.Async.Tests/AsyncTests.Creation.cs

@@ -41,7 +41,7 @@ namespace Tests
         [Fact]
         public async Task Never()
         {
-            var xs = AsyncEnumerable.Never<int>();
+            var xs = AsyncEnumerableEx.Never<int>();
 
             var e = xs.GetAsyncEnumerator();
             Assert.False(e.MoveNextAsync().IsCompleted); // Very rudimentary check

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

@@ -15,6 +15,7 @@
   <ItemGroup>
     <ProjectReference Include="..\System.Interactive.Async.Providers\System.Interactive.Async.Providers.csproj" />
     <ProjectReference Include="..\System.Interactive\System.Interactive.csproj" />
+    <ProjectReference Include="..\System.Linq.Async\System.Linq.Async.csproj" />
   </ItemGroup>
 
   <ItemGroup>

+ 0 - 5
Ix.NET/Source/System.Interactive.Async/AsyncEnumerable.cs

@@ -22,11 +22,6 @@ namespace System.Linq
             return CreateEnumerable(() => CreateEnumerator<TValue>(ct => TaskExt.False, current: null, dispose: null));
         }
 
-        public static IAsyncEnumerable<TValue> Never<TValue>()
-        {
-            return CreateEnumerable(() => CreateEnumerator<TValue>(tcs => tcs.Task, current: null, dispose: null));
-        }
-
         public static IAsyncEnumerable<TValue> Return<TValue>(TValue value)
         {
             return new[] { value }.ToAsyncEnumerable();

+ 93 - 0
Ix.NET/Source/System.Interactive.Async/AsyncEnumerableEx.cs

@@ -0,0 +1,93 @@
+// 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. 
+
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Threading.Tasks;
+using static System.Linq.AsyncEnumerable;
+
+namespace System.Linq
+{
+    public static partial class AsyncEnumerableEx
+    {
+        public static IAsyncEnumerable<TValue> Never<TValue>()
+        {
+            return CreateEnumerable(() => CreateEnumerator<TValue>(tcs => tcs.Task, current: null, dispose: null));
+        }
+
+        private static IAsyncEnumerator<T> CreateEnumerator<T>(Func<TaskCompletionSource<bool>, Task<bool>> moveNext, Func<T> current, Func<Task> dispose)
+        {
+            var self = new AnonymousAsyncIterator<T>(
+                async () =>
+                {
+                    var tcs = new TaskCompletionSource<bool>();
+
+                    var stop = new Action(() => tcs.TrySetCanceled());
+
+                    return await moveNext(tcs).ConfigureAwait(false);
+                },
+                current,
+                dispose
+            );
+
+            return self;
+        }
+
+        private sealed class AnonymousAsyncIterator<T> : AsyncIterator<T>
+        {
+            private readonly Func<T> currentFunc;
+            private readonly Func<Task> dispose;
+            private readonly Func<Task<bool>> moveNext;
+
+            public AnonymousAsyncIterator(Func<Task<bool>> moveNext, Func<T> currentFunc, Func<Task> dispose)
+            {
+                Debug.Assert(moveNext != null);
+
+                this.moveNext = moveNext;
+                this.currentFunc = currentFunc;
+                this.dispose = dispose;
+
+                // Explicit call to initialize enumerator mode
+                GetAsyncEnumerator();
+            }
+
+            public override AsyncIterator<T> Clone()
+            {
+                throw new NotSupportedException("AnonymousAsyncIterator cannot be cloned. It is only intended for use as an iterator.");
+            }
+
+            public override async Task DisposeAsync()
+            {
+                if (dispose != null)
+                {
+                    await dispose().ConfigureAwait(false);
+                }
+
+                await base.DisposeAsync().ConfigureAwait(false);
+            }
+
+            protected override async Task<bool> MoveNextCore()
+            {
+                switch (state)
+                {
+                    case AsyncIteratorState.Allocated:
+                        state = AsyncIteratorState.Iterating;
+                        goto case AsyncIteratorState.Iterating;
+
+                    case AsyncIteratorState.Iterating:
+                        if (await moveNext().ConfigureAwait(false))
+                        {
+                            current = currentFunc();
+                            return true;
+                        }
+
+                        await DisposeAsync().ConfigureAwait(false);
+                        break;
+                }
+
+                return false;
+            }
+        }
+    }
+}

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

@@ -4,4 +4,8 @@
     <TargetFrameworks>net46;netstandard1.4</TargetFrameworks>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Folder Include="System\Linq\Operators\" />
+  </ItemGroup>
+
 </Project>