forked from dotnet/corefx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
"Lavender Blue": Bringing some code from corefx master for async-stre…
…ams (C# 8.0). (dotnet#246) Bring some code from corefx master for async-streams (C# 8.0): - `IAsyncEnumerable` - `IAsyncEnumerator` - `IAsyncDisposable` - `AsyncIteratorStateMachineAttribute` - `AsyncIteratorMethodBuilder` - `ManualResetValueTaskSourceCore` Minor changes to existing code: - Add `ExecutionContext.ContextCallback<TState>(ref TState state)` delegate. - Add `ExecutionContext.RunInternal<TState>` method.
- Loading branch information
1 parent
c6a1f30
commit 3a7b5dd
Showing
30 changed files
with
1,885 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
src/Common/src/CoreLib/System/Collections/Generic/IAsyncEnumerable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// 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.Threading; | ||
|
||
namespace System.Collections.Generic | ||
{ | ||
/// <summary>Exposes an enumerator that provides asynchronous iteration over values of a specified type.</summary> | ||
/// <typeparam name="T">The type of values to enumerate.</typeparam> | ||
public interface IAsyncEnumerable<out T> | ||
{ | ||
/// <summary>Returns an enumerator that iterates asynchronously through the collection.</summary> | ||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that may be used to cancel the asynchronous iteration.</param> | ||
/// <returns>An enumerator that can be used to iterate asynchronously through the collection.</returns> | ||
IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
src/Common/src/CoreLib/System/Collections/Generic/IAsyncEnumerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
// 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.Threading.Tasks; | ||
|
||
namespace System.Collections.Generic | ||
{ | ||
/// <summary>Supports a simple asynchronous iteration over a generic collection.</summary> | ||
/// <typeparam name="T">The type of objects to enumerate.</typeparam> | ||
public interface IAsyncEnumerator<out T> : IAsyncDisposable | ||
{ | ||
/// <summary>Advances the enumerator asynchronously to the next element of the collection.</summary> | ||
/// <returns> | ||
/// A <see cref="ValueTask{Boolean}"/> that will complete with a result of <c>true</c> if the enumerator | ||
/// was successfully advanced to the next element, or <c>false</c> if the enumerator has passed the end | ||
/// of the collection. | ||
/// </returns> | ||
ValueTask<bool> MoveNextAsync(); | ||
|
||
/// <summary>Gets the element in the collection at the current position of the enumerator.</summary> | ||
T Current { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// 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.Threading.Tasks; | ||
|
||
namespace System | ||
{ | ||
/// <summary>Provides a mechanism for releasing unmanaged resources asynchronously.</summary> | ||
public interface IAsyncDisposable | ||
{ | ||
/// <summary> | ||
/// Performs application-defined tasks associated with freeing, releasing, or | ||
/// resetting unmanaged resources asynchronously. | ||
/// </summary> | ||
ValueTask DisposeAsync(); | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncIteratorMethodBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
// 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.Runtime.InteropServices; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace System.Runtime.CompilerServices | ||
{ | ||
/// <summary>Represents a builder for asynchronous iterators.</summary> | ||
[StructLayout(LayoutKind.Auto)] | ||
public struct AsyncIteratorMethodBuilder | ||
{ | ||
// AsyncIteratorMethodBuilder is used by the language compiler as part of generating | ||
// async iterators. For now, the implementation just wraps AsyncTaskMethodBuilder, as | ||
// most of the logic is shared. However, in the future this could be changed and | ||
// optimized. For example, we do need to allocate an object (once) to flow state like | ||
// ExecutionContext, which AsyncTaskMethodBuilder handles, but it handles it by | ||
// allocating a Task-derived object. We could optimize this further by removing | ||
// the Task from the hierarchy, but in doing so we'd also lose a variety of optimizations | ||
// related to it, so we'd need to replicate all of those optimizations (e.g. storing | ||
// that box object directly into a Task's continuation field). | ||
|
||
private AsyncTaskMethodBuilder _methodBuilder; // mutable struct; do not make it readonly | ||
|
||
/// <summary>Creates an instance of the <see cref="AsyncIteratorMethodBuilder"/> struct.</summary> | ||
/// <returns>The initialized instance.</returns> | ||
public static AsyncIteratorMethodBuilder Create() => | ||
#if CORERT | ||
// corert's AsyncTaskMethodBuilder.Create() currently does additional debugger-related | ||
// work, so we need to delegate to it. | ||
new AsyncIteratorMethodBuilder() { _methodBuilder = AsyncTaskMethodBuilder.Create() }; | ||
#else | ||
default; // coreclr's AsyncTaskMethodBuilder.Create just returns default as well | ||
#endif | ||
|
||
/// <summary>Invokes <see cref="IAsyncStateMachine.MoveNext"/> on the state machine while guarding the <see cref="ExecutionContext."/></summary> | ||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam> | ||
/// <param name="stateMachine">The state machine instance, passed by reference.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public void MoveNext<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine => | ||
#if CORERT | ||
_methodBuilder.Start(ref stateMachine); | ||
#else | ||
AsyncMethodBuilderCore.Start(ref stateMachine); | ||
#endif | ||
|
||
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary> | ||
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam> | ||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam> | ||
/// <param name="awaiter">The awaiter.</param> | ||
/// <param name="stateMachine">The state machine.</param> | ||
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
where TAwaiter : INotifyCompletion | ||
where TStateMachine : IAsyncStateMachine => | ||
_methodBuilder.AwaitOnCompleted(ref awaiter, ref stateMachine); | ||
|
||
/// <summary>Schedules the state machine to proceed to the next action when the specified awaiter completes.</summary> | ||
/// <typeparam name="TAwaiter">The type of the awaiter.</typeparam> | ||
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam> | ||
/// <param name="awaiter">The awaiter.</param> | ||
/// <param name="stateMachine">The state machine.</param> | ||
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
where TAwaiter : ICriticalNotifyCompletion | ||
where TStateMachine : IAsyncStateMachine => | ||
_methodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine); | ||
|
||
/// <summary>Marks iteration as being completed, whether successfully or otherwise.</summary> | ||
public void Complete() => _methodBuilder.SetResult(); | ||
|
||
/// <summary>Gets an object that may be used to uniquely identify this builder to the debugger.</summary> | ||
internal object ObjectIdForDebugger => _methodBuilder.ObjectIdForDebugger; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncIteratorStateMachineAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// 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. | ||
|
||
namespace System.Runtime.CompilerServices | ||
{ | ||
/// <summary>Indicates whether a method is an asynchronous iterator.</summary> | ||
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] | ||
public sealed class AsyncIteratorStateMachineAttribute : StateMachineAttribute | ||
{ | ||
/// <summary>Initializes a new instance of the <see cref="AsyncIteratorStateMachineAttribute"/> class.</summary> | ||
/// <param name="stateMachineType">The type object for the underlying state machine type that's used to implement a state machine method.</param> | ||
public AsyncIteratorStateMachineAttribute(Type stateMachineType) | ||
: base(stateMachineType) | ||
{ | ||
} | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
src/Common/src/CoreLib/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// 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.Runtime.InteropServices; | ||
|
||
namespace System.Runtime.CompilerServices | ||
{ | ||
/// <summary>Provides a type that can be used to configure how awaits on an <see cref="IAsyncDisposable"/> are performed.</summary> | ||
[StructLayout(LayoutKind.Auto)] | ||
public readonly struct ConfiguredAsyncDisposable | ||
{ | ||
private readonly IAsyncDisposable _source; | ||
private readonly bool _continueOnCapturedContext; | ||
|
||
internal ConfiguredAsyncDisposable(IAsyncDisposable source, bool continueOnCapturedContext) | ||
{ | ||
_source = source; | ||
_continueOnCapturedContext = continueOnCapturedContext; | ||
} | ||
|
||
public ConfiguredValueTaskAwaitable DisposeAsync() => | ||
// as with other "configured" awaitable-related type in CompilerServices, we don't null check to defend against | ||
// misuse like `default(ConfiguredAsyncDisposable).DisposeAsync()`, which will null ref by design. | ||
_source.DisposeAsync().ConfigureAwait(_continueOnCapturedContext); | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
...Common/src/CoreLib/System/Runtime/CompilerServices/ConfiguredCancelableAsyncEnumerable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// 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; | ||
|
||
namespace System.Runtime.CompilerServices | ||
{ | ||
/// <summary>Provides an awaitable async enumerable that enables cancelable iteration and configured awaits.</summary> | ||
[StructLayout(LayoutKind.Auto)] | ||
public readonly struct ConfiguredCancelableAsyncEnumerable<T> | ||
{ | ||
private readonly IAsyncEnumerable<T> _enumerable; | ||
private readonly CancellationToken _cancellationToken; | ||
private readonly bool _continueOnCapturedContext; | ||
|
||
internal ConfiguredCancelableAsyncEnumerable(IAsyncEnumerable<T> enumerable, bool continueOnCapturedContext, CancellationToken cancellationToken) | ||
{ | ||
_enumerable = enumerable; | ||
_continueOnCapturedContext = continueOnCapturedContext; | ||
_cancellationToken = cancellationToken; | ||
} | ||
|
||
/// <summary>Configures how awaits on the tasks returned from an async iteration will be performed.</summary> | ||
/// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param> | ||
/// <returns>The configured enumerable.</returns> | ||
/// <remarks>This will replace any previous value set by <see cref="ConfigureAwait(bool)"/> for this iteration.</remarks> | ||
public ConfiguredCancelableAsyncEnumerable<T> ConfigureAwait(bool continueOnCapturedContext) => | ||
new ConfiguredCancelableAsyncEnumerable<T>(_enumerable, continueOnCapturedContext, _cancellationToken); | ||
|
||
/// <summary>Sets the <see cref="CancellationToken"/> to be passed to <see cref="IAsyncEnumerable{T}.GetAsyncEnumerator(CancellationToken)"/> when iterating.</summary> | ||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to use.</param> | ||
/// <returns>The configured enumerable.</returns> | ||
/// <remarks>This will replace any previous <see cref="CancellationToken"/> set by <see cref="WithCancellation(CancellationToken)"/> for this iteration.</remarks> | ||
public ConfiguredCancelableAsyncEnumerable<T> WithCancellation(CancellationToken cancellationToken) => | ||
new ConfiguredCancelableAsyncEnumerable<T>(_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<T>).GetAsyncEnumerator()`, which will null ref by design. | ||
new Enumerator(_enumerable.GetAsyncEnumerator(_cancellationToken), _continueOnCapturedContext); | ||
|
||
/// <summary>Provides an awaitable async enumerator that enables cancelable iteration and configured awaits.</summary> | ||
[StructLayout(LayoutKind.Auto)] | ||
public readonly struct Enumerator | ||
{ | ||
private readonly IAsyncEnumerator<T> _enumerator; | ||
private readonly bool _continueOnCapturedContext; | ||
|
||
internal Enumerator(IAsyncEnumerator<T> enumerator, bool continueOnCapturedContext) | ||
{ | ||
_enumerator = enumerator; | ||
_continueOnCapturedContext = continueOnCapturedContext; | ||
} | ||
|
||
/// <summary>Advances the enumerator asynchronously to the next element of the collection.</summary> | ||
/// <returns> | ||
/// A <see cref="ConfiguredValueTaskAwaitable{Boolean}"/> that will complete with a result of <c>true</c> | ||
/// if the enumerator was successfully advanced to the next element, or <c>false</c> if the enumerator has | ||
/// passed the end of the collection. | ||
/// </returns> | ||
public ConfiguredValueTaskAwaitable<bool> MoveNextAsync() => | ||
_enumerator.MoveNextAsync().ConfigureAwait(_continueOnCapturedContext); | ||
|
||
/// <summary>Gets the element in the collection at the current position of the enumerator.</summary> | ||
public T Current => _enumerator.Current; | ||
|
||
/// <summary> | ||
/// Performs application-defined tasks associated with freeing, releasing, or | ||
/// resetting unmanaged resources asynchronously. | ||
/// </summary> | ||
public ConfiguredValueTaskAwaitable DisposeAsync() => | ||
_enumerator.DisposeAsync().ConfigureAwait(_continueOnCapturedContext); | ||
} | ||
} | ||
} |
Oops, something went wrong.