Created
June 3, 2018 02:04
-
-
Save jcouv/1d5de1b27e0a4da6608dbd784356200c to your computer and use it in GitHub Desktop.
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
class C | |
{ | |
static async System.Collections.Generic.IAsyncEnumerable<int> M() | |
{ | |
System.Console.Write(""1 ""); | |
await System.Threading.Tasks.Task.CompletedTask; | |
System.Console.Write(""2 ""); | |
yield return 3; | |
System.Console.Write("" 4 ""); | |
} | |
static async System.Threading.Tasks.Task Main() | |
{ | |
System.Console.Write(""0 ""); | |
foreach await (var i in M()) | |
{ | |
System.Console.Write(i); | |
} | |
System.Console.Write(""5""); | |
} | |
} | |
// -------------------------------------------------------------------------------------------------------------- | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.ExceptionServices; | |
using System.Threading.Tasks; | |
using System.Threading.Tasks.Sources; | |
[assembly: CompilationRelaxations (8)] | |
[assembly: RuntimeCompatibility (WrapNonExceptionThrows = true)] | |
[assembly: Debuggable (DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] | |
[assembly: AssemblyVersion ("0.0.0.0")] | |
internal class C | |
{ | |
[CompilerGenerated] | |
private sealed class <M>d__0 : IAsyncEnumerable<int>, IAsyncEnumerator<int>, IAsyncDisposable, IValueTaskSource<bool>, IStrongBox<ManualResetValueTaskSourceLogic<bool>>, IAsyncStateMachine | |
{ | |
public int <>1__state; | |
public AsyncVoidMethodBuilder <>t__builder; | |
private int <>2__current; | |
public ManualResetValueTaskSourceLogic<bool> <>v__promiseOfValueOrEnd; | |
public bool <>w__promiseIsActive; | |
private TaskAwaiter <>u__1; | |
ManualResetValueTaskSourceLogic<bool> IStrongBox<ManualResetValueTaskSourceLogic<bool>>.Value { | |
[DebuggerHidden] | |
get { | |
return ref <>v__promiseOfValueOrEnd; | |
} | |
} | |
private void MoveNext () | |
{ | |
int num = <>1__state; | |
try { | |
TaskAwaiter awaiter; | |
int <>1__state2; | |
switch (num) { | |
default: | |
Console.Write ("1 "); | |
awaiter = Task.CompletedTask.GetAwaiter (); | |
if (!awaiter.IsCompleted) { | |
num = (<>1__state = 0); | |
<>u__1 = awaiter; | |
if (!<>w__promiseIsActive) { | |
<>w__promiseIsActive = true; | |
<>v__promiseOfValueOrEnd.Reset (); | |
} | |
<M>d__0 <M>d__ = this; | |
<>t__builder.AwaitUnsafeOnCompleted (ref awaiter, ref <M>d__); | |
return; | |
} | |
goto IL_0097; | |
case 0: | |
awaiter = <>u__1; | |
<>u__1 = default(TaskAwaiter); | |
num = (<>1__state = -1); | |
goto IL_0097; | |
case 1: | |
break; | |
IL_0097: | |
awaiter.GetResult (); | |
Console.Write ("2 "); | |
<>2__current = 3; | |
<>1__state2 = <>1__state; | |
<>1__state = 1; | |
if (<>w__promiseIsActive) { | |
<>v__promiseOfValueOrEnd.SetResult (true); | |
} | |
return; | |
} | |
Console.Write (" 4 "); | |
} catch (Exception exception) { | |
<>1__state = -2; | |
<>t__builder.SetException (exception); | |
return; | |
} | |
<>1__state = -2; | |
<>t__builder.SetResult (); | |
} | |
void IAsyncStateMachine.MoveNext () | |
{ | |
//ILSpy generated this explicit interface implementation from .override directive in MoveNext | |
this.MoveNext (); | |
} | |
[DebuggerHidden] | |
private void SetStateMachine (IAsyncStateMachine stateMachine) | |
{ | |
} | |
void IAsyncStateMachine.SetStateMachine (IAsyncStateMachine stateMachine) | |
{ | |
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine | |
this.SetStateMachine (stateMachine); | |
} | |
[DebuggerHidden] | |
IAsyncEnumerator<int> IAsyncEnumerable<int>.GetAsyncEnumerator () | |
{ | |
return this; | |
} | |
[DebuggerHidden] | |
int IAsyncEnumerator<int>.TryGetNext (out bool success) | |
{ | |
if (<>w__promiseIsActive) { | |
<>w__promiseIsActive = false; | |
} else { | |
<M>d__0 <M>d__ = this; | |
<>t__builder.Start (ref <M>d__); | |
} | |
if (!<>w__promiseIsActive && <>1__state != -2) { | |
success = true; | |
return <>2__current; | |
} | |
success = false; | |
return 0; | |
} | |
[DebuggerHidden] | |
ValueTask<bool> IAsyncEnumerator<int>.WaitForNextAsync () | |
{ | |
if (<>1__state == -2) { | |
return default(ValueTask<bool>); | |
} | |
if (<>w__promiseIsActive || <>1__state == -1) { | |
<M>d__0 <M>d__ = this; | |
<>t__builder.Start (ref <M>d__); | |
} | |
return new ValueTask<bool> (this, <>v__promiseOfValueOrEnd.Version); | |
} | |
[DebuggerHidden] | |
bool IValueTaskSource<bool>.GetResult (short token) | |
{ | |
return <>v__promiseOfValueOrEnd.GetResult (token); | |
} | |
[DebuggerHidden] | |
ValueTaskSourceStatus IValueTaskSource<bool>.GetStatus (short token) | |
{ | |
return <>v__promiseOfValueOrEnd.GetStatus (token); | |
} | |
[DebuggerHidden] | |
void IValueTaskSource<bool>.OnCompleted (Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) | |
{ | |
<>v__promiseOfValueOrEnd.OnCompleted (continuation, state, token, flags); | |
} | |
[DebuggerHidden] | |
ValueTask IAsyncDisposable.DisposeAsync () | |
{ | |
<>v__promiseOfValueOrEnd.Reset (); | |
<>1__state = -1; | |
return default(ValueTask); | |
} | |
} | |
[CompilerGenerated] | |
private sealed class <Main>d__1 : IAsyncStateMachine | |
{ | |
public int <>1__state; | |
public AsyncTaskMethodBuilder <>t__builder; | |
private IAsyncEnumerator<int> <>s__1; | |
private object <>s__2; | |
private int <>s__3; | |
private int <i>5__4; | |
private bool <>s__5; | |
private ValueTaskAwaiter<bool> <>u__1; | |
private ValueTaskAwaiter <>u__2; | |
private void MoveNext () | |
{ | |
int num = <>1__state; | |
try { | |
ValueTaskAwaiter awaiter; | |
object obj2; | |
switch (num) { | |
default: | |
Console.Write ("0 "); | |
<>s__1 = M ().GetAsyncEnumerator (); | |
<>s__2 = null; | |
<>s__3 = 0; | |
goto case 0; | |
case 0: { | |
<Main>d__1 <Main>d__; | |
try { | |
if (num != 0) { | |
goto IL_0075; | |
} | |
ValueTaskAwaiter<bool> awaiter2 = <>u__1; | |
<>u__1 = default(ValueTaskAwaiter<bool>); | |
num = (<>1__state = -1); | |
goto IL_00d6; | |
IL_0075: | |
awaiter2 = <>s__1.WaitForNextAsync ().GetAwaiter (); | |
if (!awaiter2.IsCompleted) { | |
num = (<>1__state = 0); | |
<>u__1 = awaiter2; | |
<Main>d__ = this; | |
<>t__builder.AwaitUnsafeOnCompleted (ref awaiter2, ref <Main>d__); | |
return; | |
} | |
goto IL_00d6; | |
IL_00d6: | |
<>s__5 = awaiter2.GetResult (); | |
if (<>s__5) { | |
while (true) { | |
<i>5__4 = <>s__1.TryGetNext (out bool flag); | |
if (flag) { | |
Console.Write (<i>5__4); | |
continue; | |
} | |
break; | |
} | |
goto IL_0075; | |
} | |
} catch (object obj) { | |
obj2 = (<>s__2 = obj); | |
} | |
if (<>s__1 == null) { | |
break; | |
} | |
awaiter = <>s__1.DisposeAsync ().GetAwaiter (); | |
if (!awaiter.IsCompleted) { | |
num = (<>1__state = 1); | |
<>u__2 = awaiter; | |
<Main>d__ = this; | |
<>t__builder.AwaitUnsafeOnCompleted (ref awaiter, ref <Main>d__); | |
return; | |
} | |
goto IL_0169; | |
} | |
case 1: | |
{ | |
awaiter = <>u__2; | |
<>u__2 = default(ValueTaskAwaiter); | |
num = (<>1__state = -1); | |
goto IL_0169; | |
} | |
IL_0169: | |
awaiter.GetResult (); | |
break; | |
} | |
obj2 = <>s__2; | |
if (obj2 != null) { | |
Exception ex = obj2 as Exception; | |
if (ex == null) { | |
throw obj2; | |
} | |
ExceptionDispatchInfo.Capture (ex).Throw (); | |
} | |
int <>s__6 = <>s__3; | |
<>s__2 = null; | |
<>s__1 = null; | |
Console.Write ("5"); | |
} catch (Exception exception) { | |
<>1__state = -2; | |
<>t__builder.SetException (exception); | |
return; | |
} | |
<>1__state = -2; | |
<>t__builder.SetResult (); | |
} | |
void IAsyncStateMachine.MoveNext () | |
{ | |
//ILSpy generated this explicit interface implementation from .override directive in MoveNext | |
this.MoveNext (); | |
} | |
[DebuggerHidden] | |
private void SetStateMachine (IAsyncStateMachine stateMachine) | |
{ | |
} | |
void IAsyncStateMachine.SetStateMachine (IAsyncStateMachine stateMachine) | |
{ | |
//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine | |
this.SetStateMachine (stateMachine); | |
} | |
} | |
[AsyncStateMachine (typeof(<M>d__0))] | |
[DebuggerStepThrough] | |
private static IAsyncEnumerable<int> M () | |
{ | |
<M>d__0 <M>d__ = new <M>d__0 (); | |
<M>d__.<>t__builder = AsyncVoidMethodBuilder.Create (); | |
<M>d__.<>1__state = -1; | |
AsyncVoidMethodBuilder <>t__builder = <M>d__.<>t__builder; | |
<M>d__.<>v__promiseOfValueOrEnd = new ManualResetValueTaskSourceLogic<bool> (<M>d__); | |
<M>d__.<>w__promiseIsActive = true; | |
return <M>d__; | |
} | |
[AsyncStateMachine (typeof(<Main>d__1))] | |
[DebuggerStepThrough] | |
private static Task Main () | |
{ | |
<Main>d__1 <Main>d__ = new <Main>d__1 (); | |
<Main>d__.<>t__builder = AsyncTaskMethodBuilder.Create (); | |
<Main>d__.<>1__state = -1; | |
AsyncTaskMethodBuilder <>t__builder = <Main>d__.<>t__builder; | |
<>t__builder.Start (ref <Main>d__); | |
return <Main>d__.<>t__builder.Task; | |
} | |
private static void <Main> () | |
{ | |
Main ().GetAwaiter ().GetResult (); | |
} | |
} | |
namespace System | |
{ | |
public interface IAsyncDisposable | |
{ | |
ValueTask DisposeAsync (); | |
} | |
} | |
namespace System.Threading.Tasks | |
{ | |
public struct ManualResetValueTaskSourceLogic<TResult> | |
{ | |
private static readonly Action<object> s_sentinel = delegate { | |
throw new InvalidOperationException (); | |
}; | |
private readonly IStrongBox<ManualResetValueTaskSourceLogic<TResult>> _parent; | |
private Action<object> _continuation; | |
private object _continuationState; | |
private object _capturedContext; | |
private ExecutionContext _executionContext; | |
private bool _completed; | |
private TResult _result; | |
private ExceptionDispatchInfo _error; | |
private short _version; | |
public short Version => _version; | |
public ManualResetValueTaskSourceLogic (IStrongBox<ManualResetValueTaskSourceLogic<TResult>> parent) | |
{ | |
if (parent == null) { | |
throw new ArgumentNullException ("parent"); | |
} | |
_parent = parent; | |
_continuation = null; | |
_continuationState = null; | |
_capturedContext = null; | |
_executionContext = null; | |
_completed = false; | |
_result = default(TResult); | |
_error = null; | |
_version = 0; | |
} | |
private void ValidateToken (short token) | |
{ | |
if (token == _version) { | |
return; | |
} | |
throw new InvalidOperationException (); | |
} | |
public ValueTaskSourceStatus GetStatus (short token) | |
{ | |
ValidateToken (token); | |
return _completed ? ((_error == null) ? ValueTaskSourceStatus.Succeeded : ((_error.SourceException is OperationCanceledException) ? ValueTaskSourceStatus.Canceled : ValueTaskSourceStatus.Faulted)) : ValueTaskSourceStatus.Pending; | |
} | |
public TResult GetResult (short token) | |
{ | |
ValidateToken (token); | |
if (!_completed) { | |
throw new InvalidOperationException (); | |
} | |
_error?.Throw (); | |
return _result; | |
} | |
public void Reset () | |
{ | |
_version++; | |
_completed = false; | |
_continuation = null; | |
_continuationState = null; | |
_result = default(TResult); | |
_error = null; | |
_executionContext = null; | |
_capturedContext = null; | |
} | |
public void OnCompleted (Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) | |
{ | |
if (continuation == null) { | |
throw new ArgumentNullException ("continuation"); | |
} | |
ValidateToken (token); | |
if ((flags & ValueTaskSourceOnCompletedFlags.FlowExecutionContext) != 0) { | |
_executionContext = ExecutionContext.Capture (); | |
} | |
if ((flags & ValueTaskSourceOnCompletedFlags.UseSchedulingContext) != 0) { | |
SynchronizationContext current = SynchronizationContext.Current; | |
if (current != null && current.GetType () != typeof(SynchronizationContext)) { | |
_capturedContext = current; | |
} else { | |
TaskScheduler current2 = TaskScheduler.Current; | |
if (current2 != TaskScheduler.Default) { | |
_capturedContext = current2; | |
} | |
} | |
} | |
_continuationState = state; | |
if (Interlocked.CompareExchange<Action<object>> (ref _continuation, continuation, (Action<object>)null) != null) { | |
_executionContext = null; | |
object capturedContext = _capturedContext; | |
_capturedContext = null; | |
object obj = capturedContext; | |
object obj2 = obj; | |
if (obj2 != null) { | |
SynchronizationContext synchronizationContext; | |
if ((synchronizationContext = (obj2 as SynchronizationContext)) == null) { | |
TaskScheduler taskScheduler; | |
if ((taskScheduler = (obj2 as TaskScheduler)) != null) { | |
TaskScheduler scheduler = taskScheduler; | |
Task.Factory.StartNew (continuation, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, scheduler); | |
} | |
} else { | |
SynchronizationContext synchronizationContext2 = synchronizationContext; | |
synchronizationContext2.Post (delegate (object s) { | |
Tuple<Action<object>, object> tuple = (Tuple<Action<object>, object>)s; | |
tuple.Item1 (tuple.Item2); | |
}, Tuple.Create<Action<object>, object> (continuation, state)); | |
} | |
} else { | |
Task.Factory.StartNew (continuation, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); | |
} | |
} | |
} | |
public void SetResult (TResult result) | |
{ | |
_result = result; | |
SignalCompletion (); | |
} | |
public void SetException (Exception error) | |
{ | |
_error = ExceptionDispatchInfo.Capture (error); | |
SignalCompletion (); | |
} | |
private void SignalCompletion () | |
{ | |
if (_completed) { | |
throw new InvalidOperationException (); | |
} | |
_completed = true; | |
if (Interlocked.CompareExchange<Action<object>> (ref _continuation, s_sentinel, (Action<object>)null) != null) { | |
if (_executionContext != null) { | |
ExecutionContext executionContext = _executionContext; | |
ContextCallback callback = delegate (object s) { | |
((IStrongBox<ManualResetValueTaskSourceLogic<TResult>>)s).Value.InvokeContinuation (); | |
}; | |
IStrongBox<ManualResetValueTaskSourceLogic<TResult>> parent = _parent; | |
if (parent == null) { | |
throw new InvalidOperationException (); | |
} | |
ExecutionContext.Run (executionContext, callback, parent); | |
} else { | |
InvokeContinuation (); | |
} | |
} | |
} | |
private void InvokeContinuation () | |
{ | |
object capturedContext = _capturedContext; | |
_capturedContext = null; | |
object obj = capturedContext; | |
object obj2 = obj; | |
if (obj2 != null) { | |
SynchronizationContext synchronizationContext; | |
if ((synchronizationContext = (obj2 as SynchronizationContext)) == null) { | |
TaskScheduler taskScheduler; | |
if ((taskScheduler = (obj2 as TaskScheduler)) != null) { | |
TaskScheduler scheduler = taskScheduler; | |
Task.Factory.StartNew (_continuation, _continuationState, CancellationToken.None, TaskCreationOptions.DenyChildAttach, scheduler); | |
} | |
} else { | |
SynchronizationContext synchronizationContext2 = synchronizationContext; | |
SynchronizationContext synchronizationContext3 = synchronizationContext2; | |
SendOrPostCallback d = delegate (object s) { | |
ref ManualResetValueTaskSourceLogic<TResult> value = ref ((IStrongBox<ManualResetValueTaskSourceLogic<TResult>>)s).Value; | |
value._continuation (value._continuationState); | |
}; | |
IStrongBox<ManualResetValueTaskSourceLogic<TResult>> parent = _parent; | |
if (parent == null) { | |
throw new InvalidOperationException (); | |
} | |
synchronizationContext3.Post (d, parent); | |
} | |
} else { | |
_continuation (_continuationState); | |
} | |
} | |
} | |
} | |
namespace System.Runtime.CompilerServices | |
{ | |
public interface IStrongBox<T> | |
{ | |
ref T Value { | |
get; | |
} | |
} | |
} | |
namespace System.Collections.Generic | |
{ | |
public interface IAsyncEnumerable<out T> | |
{ | |
IAsyncEnumerator<T> GetAsyncEnumerator (); | |
} | |
public interface IAsyncEnumerator<out T> : IAsyncDisposable | |
{ | |
ValueTask<bool> WaitForNextAsync (); | |
T TryGetNext (out bool success); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment