Browse Source

Embrace LDM-2018-11-28 decision to check for cancellation in GetAsyncEnumerator.

Bart De Smet 7 years ago
parent
commit
8b7d90e758

+ 2 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Never.cs

@@ -21,6 +21,8 @@ namespace System.Linq
 
             public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
                 return new NeverAsyncEnumerator(cancellationToken);
             }
 

+ 2 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Return.cs

@@ -28,6 +28,8 @@ namespace System.Linq
 
             public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
                 return new ReturnEnumerator(_value);
             }
 

+ 2 - 0
Ix.NET/Source/System.Interactive.Async/System/Linq/Operators/Throw.cs

@@ -37,6 +37,8 @@ namespace System.Linq
 
             public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
             {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
                 return new ThrowEnumerator(_moveNextThrows);
             }
 

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

@@ -118,6 +118,8 @@ namespace System.Linq
         /// <returns>A new enumerator instance used to enumerate the elements in the sequence.</returns>
         public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken token)
         {
+            token.ThrowIfCancellationRequested();
+
             if (_enumerable == null)
             {
                 var expression = Expression.Lambda<Func<IAsyncEnumerable<T>>>(new AsyncEnumerableRewriter().Visit(_expression), null);

+ 7 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/AsyncEnumerable.cs

@@ -38,7 +38,12 @@ namespace System.Linq
                 _getEnumerator = getEnumerator;
             }
 
-            public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken) => _getEnumerator(cancellationToken);
+            public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken)
+            {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+                return _getEnumerator(cancellationToken);
+            }
         }
 
         // REVIEW: Explicit implementation of the interfaces allows for composition with other "modifier operators" such as ConfigureAwait.
@@ -56,6 +61,7 @@ namespace System.Linq
             }
 
             // REVIEW: Should we simply ignore the second cancellation token or should we link the two?
+            // REVIEW: [LDM-2018-11-28] Should we have eager cancellation here too?
 
             public WithCancellationAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken)
                 => new WithCancellationAsyncEnumerator(_source.GetAsyncEnumerator(_cancellationToken));

+ 2 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/AsyncIterator.cs

@@ -30,6 +30,8 @@ namespace System.Linq
 
         public IAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken)
         {
+            cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
             var enumerator = _state == AsyncIteratorState.New && _threadId == Environment.CurrentManagedThreadId
                 ? this
                 : Clone();

+ 6 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Empty.cs

@@ -42,7 +42,12 @@ namespace System.Linq
 
             public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(false);
 
-            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken) => this;
+            public IAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken)
+            {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+                return this;
+            }
 
             public ValueTask DisposeAsync() => default;
         }

+ 15 - 3
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/GroupJoin.cs

@@ -136,7 +136,10 @@ namespace System.Linq
             }
 
             public IAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken)
-                => new GroupJoinAsyncEnumerator(
+            {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+                return new GroupJoinAsyncEnumerator(
                     _outer.GetAsyncEnumerator(cancellationToken),
                     _inner,
                     _outerKeySelector,
@@ -144,6 +147,7 @@ namespace System.Linq
                     _resultSelector,
                     _comparer,
                     cancellationToken);
+            }
 
             private sealed class GroupJoinAsyncEnumerator : IAsyncEnumerator<TResult>
             {
@@ -230,7 +234,10 @@ namespace System.Linq
             }
 
             public IAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken)
-                => new GroupJoinAsyncEnumeratorWithTask(
+            {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+                return new GroupJoinAsyncEnumeratorWithTask(
                     _outer.GetAsyncEnumerator(cancellationToken),
                     _inner,
                     _outerKeySelector,
@@ -238,6 +245,7 @@ namespace System.Linq
                     _resultSelector,
                     _comparer,
                     cancellationToken);
+            }
 
             private sealed class GroupJoinAsyncEnumeratorWithTask : IAsyncEnumerator<TResult>
             {
@@ -325,7 +333,10 @@ namespace System.Linq
             }
 
             public IAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken)
-                => new GroupJoinAsyncEnumeratorWithTask(
+            {
+                cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+                return new GroupJoinAsyncEnumeratorWithTask(
                     _outer.GetAsyncEnumerator(cancellationToken),
                     _inner,
                     _outerKeySelector,
@@ -333,6 +344,7 @@ namespace System.Linq
                     _resultSelector,
                     _comparer,
                     cancellationToken);
+            }
 
             private sealed class GroupJoinAsyncEnumeratorWithTask : IAsyncEnumerator<TResult>
             {

+ 6 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Grouping.cs

@@ -89,6 +89,11 @@ namespace System.Linq.Internal
             }
         }
 
-        IAsyncEnumerator<TElement> IAsyncEnumerable<TElement>.GetAsyncEnumerator(CancellationToken cancellationToken) => this.ToAsyncEnumerable().GetAsyncEnumerator(cancellationToken);
+        IAsyncEnumerator<TElement> IAsyncEnumerable<TElement>.GetAsyncEnumerator(CancellationToken cancellationToken)
+        {
+            cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+            return this.ToAsyncEnumerable().GetAsyncEnumerator(cancellationToken);
+        }
     }
 }

+ 4 - 0
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Lookup.cs

@@ -274,6 +274,8 @@ namespace System.Linq.Internal
 
         IAsyncEnumerator<IAsyncGrouping<TKey, TElement>> IAsyncEnumerable<IAsyncGrouping<TKey, TElement>>.GetAsyncEnumerator(CancellationToken cancellationToken)
         {
+            cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
             return Enumerable.Cast<IAsyncGrouping<TKey, TElement>>(this).ToAsyncEnumerable().GetAsyncEnumerator(cancellationToken);
         }
 
@@ -687,6 +689,8 @@ namespace System.Linq.Internal
 
         IAsyncEnumerator<IAsyncGrouping<TKey, TElement>> IAsyncEnumerable<IAsyncGrouping<TKey, TElement>>.GetAsyncEnumerator(CancellationToken cancellationToken)
         {
+            cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
             return Enumerable.Cast<IAsyncGrouping<TKey, TElement>>(this).ToAsyncEnumerable().GetAsyncEnumerator(cancellationToken);
         }
 

+ 6 - 2
Ix.NET/Source/System.Linq.Async/System/Threading/Tasks/AsyncEnumerableExtensions.cs

@@ -33,8 +33,12 @@ namespace System.Threading.Tasks
                     _continueOnCapturedContext = continueOnCapturedContext;
                 }
 
-                public ConfiguredAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken) =>
-                    new ConfiguredAsyncEnumerator(_enumerable.GetAsyncEnumerator(cancellationToken), _continueOnCapturedContext);
+                public ConfiguredAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken)
+                {
+                    cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
+
+                    return new ConfiguredAsyncEnumerator(_enumerable.GetAsyncEnumerator(cancellationToken), _continueOnCapturedContext);
+                }
 
                 IAsyncEnumerator<T> IAsyncEnumerable<T>.GetAsyncEnumerator(CancellationToken cancellationToken) =>
                     GetAsyncEnumerator(cancellationToken);