Browse Source

IgnoreElements

Oren Novotny 9 years ago
parent
commit
ab1a2032b5
1 changed files with 47 additions and 24 deletions
  1. 47 24
      Ix.NET/Source/System.Interactive.Async/IgnoreElements.cs

+ 47 - 24
Ix.NET/Source/System.Interactive.Async/IgnoreElements.cs

@@ -17,34 +17,57 @@ namespace System.Linq
             if (source == null)
                 throw new ArgumentNullException(nameof(source));
 
-            return CreateEnumerable(
-                () =>
+            return new IgnoreElementsAsyncIterator<TSource>(source);
+        }
+
+        private sealed class IgnoreElementsAsyncIterator<TSource> : AsyncIterator<TSource>
+        {
+            private readonly IAsyncEnumerable<TSource> source;
+            private IAsyncEnumerator<TSource> enumerator;
+
+            public IgnoreElementsAsyncIterator(IAsyncEnumerable<TSource> source)
+            {
+                this.source = source;
+            }
+
+            public override AsyncIterator<TSource> Clone()
+            {
+                return new IgnoreElementsAsyncIterator<TSource>(source);
+            }
+
+            public override void Dispose()
+            {
+                if (enumerator != null)
                 {
-                    var e = source.GetEnumerator();
+                    enumerator.Dispose();
+                    enumerator = null;
+                }
+
+                base.Dispose();
+            }
 
-                    var cts = new CancellationTokenDisposable();
-                    var d = Disposable.Create(cts, e);
+            protected override async Task<bool> MoveNextCore(CancellationToken cancellationToken)
+            {
+                switch (state)
+                {
+                    case AsyncIteratorState.Allocated:
+                        enumerator = source.GetEnumerator();
+                        state = AsyncIteratorState.Iterating;
+                        goto case AsyncIteratorState.Iterating;
 
-                    var f = default(Func<CancellationToken, Task<bool>>);
-                    f = async ct =>
+                    case AsyncIteratorState.Iterating:
+                        if (!await enumerator.MoveNext(cancellationToken)
+                                             .ConfigureAwait(false))
                         {
-                            if (!await e.MoveNext(ct)
-                                        .ConfigureAwait(false))
-                            {
-                                return false;
-                            }
-
-                            return await f(ct)
-                                       .ConfigureAwait(false);
-                        };
-
-                    return CreateEnumerator<TSource>(
-                        f,
-                        () => { throw new InvalidOperationException(); },
-                        d.Dispose,
-                        e
-                    );
-                });
+                            break;
+                        }
+
+                        goto case AsyncIteratorState.Iterating; // Loop
+                }
+
+                Dispose();
+                return false;
+            }
         }
     }
 }