#if !BCL_HAS_CONFIGUREAWAIT // https://github.com/dotnet/coreclr/pull/21939 // 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.Collections.Generic; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace System.Runtime.CompilerServices { /// Provides an awaitable async enumerable that enables cancelable iteration and configured awaits. [StructLayout(LayoutKind.Auto)] public readonly struct ConfiguredCancelableAsyncEnumerable { private readonly IAsyncEnumerable _enumerable; private readonly CancellationToken _cancellationToken; private readonly bool _continueOnCapturedContext; internal ConfiguredCancelableAsyncEnumerable(IAsyncEnumerable enumerable, bool continueOnCapturedContext, CancellationToken cancellationToken) { _enumerable = enumerable; _continueOnCapturedContext = continueOnCapturedContext; _cancellationToken = cancellationToken; } /// Configures how awaits on the tasks returned from an async iteration will be performed. /// Whether to capture and marshal back to the current context. /// The configured enumerable. /// This will replace any previous value set by for this iteration. public ConfiguredCancelableAsyncEnumerable ConfigureAwait(bool continueOnCapturedContext) => new ConfiguredCancelableAsyncEnumerable(_enumerable, continueOnCapturedContext, _cancellationToken); /// Sets the to be passed to when iterating. /// The to use. /// The configured enumerable. /// This will replace any previous set by for this iteration. public ConfiguredCancelableAsyncEnumerable WithCancellation(CancellationToken cancellationToken) => new ConfiguredCancelableAsyncEnumerable(_enumerable, _continueOnCapturedContext, cancellationToken); public Enumerator GetAsyncEnumerator() => // as with other "configured" awaitable-related type in CompilerServices, we don't null check to defend against // misuse like `default(ConfiguredCancelableAsyncEnumerable).GetAsyncEnumerator()`, which will null ref by design. new Enumerator(_enumerable.GetAsyncEnumerator(_cancellationToken), _continueOnCapturedContext); /// Provides an awaitable async enumerator that enables cancelable iteration and configured awaits. [StructLayout(LayoutKind.Auto)] public readonly struct Enumerator { private readonly IAsyncEnumerator _enumerator; private readonly bool _continueOnCapturedContext; internal Enumerator(IAsyncEnumerator enumerator, bool continueOnCapturedContext) { _enumerator = enumerator; _continueOnCapturedContext = continueOnCapturedContext; } /// Advances the enumerator asynchronously to the next element of the collection. /// /// A that will complete with a result of true /// if the enumerator was successfully advanced to the next element, or false if the enumerator has /// passed the end of the collection. /// public ConfiguredValueTaskAwaitable MoveNextAsync() => _enumerator.MoveNextAsync().ConfigureAwait(_continueOnCapturedContext); /// Gets the element in the collection at the current position of the enumerator. public T Current => _enumerator.Current; /// /// Performs application-defined tasks associated with freeing, releasing, or /// resetting unmanaged resources asynchronously. /// public ConfiguredValueTaskAwaitable DisposeAsync() => _enumerator.DisposeAsync().ConfigureAwait(_continueOnCapturedContext); } } } #else using System.Runtime.CompilerServices; [assembly: TypeForwardedTo(typeof(ConfiguredCancelableAsyncEnumerable<>))] #endif