Skip to content

Instantly share code, notes, and snippets.

@jcouv
Created June 3, 2018 02:04
Show Gist options
  • Save jcouv/1d5de1b27e0a4da6608dbd784356200c to your computer and use it in GitHub Desktop.
Save jcouv/1d5de1b27e0a4da6608dbd784356200c to your computer and use it in GitHub Desktop.
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