#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