Skip to content

Instantly share code, notes, and snippets.

@aetos382
Last active February 13, 2026 11:00
Show Gist options
  • Select an option

  • Save aetos382/da0df99431222a9d8f47c8eece3605db to your computer and use it in GitHub Desktop.

Select an option

Save aetos382/da0df99431222a9d8f47c8eece3605db to your computer and use it in GitHub Desktop.
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
Console.WriteLine(await S());
Console.WriteLine(await T());
try
{
var myTask = MyT();
((ICriticalNotifyCompletion)myTask.GetAwaiter()).UnsafeOnCompleted(static () => Console.WriteLine("co1"));
((ICriticalNotifyCompletion)myTask.GetAwaiter()).UnsafeOnCompleted(static () => throw new Exception("ah"));
((ICriticalNotifyCompletion)myTask.GetAwaiter()).UnsafeOnCompleted(static () => Console.WriteLine("co2"));
Console.WriteLine("X");
await myTask;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
partial class Program
{
private static async Task<int> S()
{
var i = 100;
i = await IncrementAsync(i, "step 1");
i = await IncrementAsync(i, "step 2", false);
i = await IncrementAsync(i, "step 3");
return i;
}
private static async MyTask<int> T()
{
var i = 100;
i = await IncrementAsync(i, "step 1");
i = await IncrementAsync(i, "step 2", false);
i = await IncrementAsync(i, "step 3");
return i;
}
[AsyncStateMachine(typeof(StateMachine))]
private static MyTask<int> MyT()
{
var builder = MyTaskMethodBuilder<int>.Create();
var stateMachine = new StateMachine(builder);
builder.Start(ref stateMachine);
var task = builder.Task;
return task;
}
private static async Task<int> IncrementAsync(int value, string label, bool completeSynchronously = true)
{
if (!completeSynchronously)
{
await Task.Delay(1);
}
return value + 1;
}
}
[AsyncMethodBuilder(typeof(MyTaskMethodBuilder<>))]
class MyTask<T>
{
public static MyTask<T> FromResult(T result)
{
return new()
{
_result = result,
_state = MyTaskState.Success
};
}
public static MyTask<T> FromException(Exception exception)
{
return new()
{
_exception = exception,
_state = MyTaskState.Failed
};
}
public MyTaskAwaiter<T> GetAwaiter()
{
return new MyTaskAwaiter<T>(this);
}
public T GetResult()
{
if (!IsCompleted)
{
var block = _block = new ManualResetEventSlim();
block.Wait();
block.Dispose();
}
switch (_state)
{
case MyTaskState.Success:
return _result!;
case MyTaskState.Failed:
ExceptionDispatchInfo.Throw(_exception!);
throw new UnreachableException();
default:
throw new InvalidOperationException();
}
}
private MyTaskState _state = MyTaskState.RanToCompletion;
private T? _result;
private Exception? _exception;
private ManualResetEventSlim? _block;
private readonly ConcurrentQueue<Action> _continuationActions = new();
private readonly ConcurrentQueue<Action> _unsafeContinuationActions = new();
internal void SetResult(T result)
{
if (Interlocked.CompareExchange(ref _state, MyTaskState.Success, MyTaskState.RanToCompletion) != MyTaskState.RanToCompletion)
{
throw new InvalidOperationException();
}
_result = result;
RunCallbacks();
_block?.Set();
}
internal void SetException(Exception exception)
{
if (Interlocked.CompareExchange(ref _state, MyTaskState.Failed, MyTaskState.RanToCompletion) != MyTaskState.RanToCompletion)
{
throw new InvalidOperationException();
}
_exception = exception;
RunCallbacks();
_block?.Set();
}
internal bool IsCompleted => _state is not MyTaskState.RanToCompletion;
private void RunCallbacks()
{
var exceptions = new List<Exception>();
while (_continuationActions.TryDequeue(out var action))
{
try
{
action();
}
catch (Exception e)
{
exceptions.Add(e);
}
}
using var flowControl = ExecutionContext.SuppressFlow();
while (_unsafeContinuationActions.TryDequeue(out var action))
{
try
{
action();
}
catch (Exception e)
{
exceptions.Add(e);
}
}
if (exceptions.Count != 0)
{
throw new AggregateException(exceptions);
}
}
internal void OnCompleted(Action continuation)
{
_continuationActions.Enqueue(continuation);
if (IsCompleted)
{
RunCallbacks();
}
}
internal void UnsafeOnCompleted(Action continuation)
{
_unsafeContinuationActions.Enqueue(continuation);
if (IsCompleted)
{
RunCallbacks();
}
}
}
public enum MyTaskState
{
RanToCompletion,
Success,
Failed
}
public class MyTaskAwaiter<T> :
ICriticalNotifyCompletion
{
private readonly MyTask<T> _task;
internal MyTaskAwaiter(MyTask<T> task)
{
_task = task;
}
public bool IsCompleted => _task.IsCompleted;
void INotifyCompletion.OnCompleted(Action continuation)
{
_task.OnCompleted(continuation);
}
void ICriticalNotifyCompletion.UnsafeOnCompleted(Action continuation)
{
_task.UnsafeOnCompleted(continuation);
}
public T GetResult()
{
return _task.GetResult();
}
}
class MyTaskMethodBuilder<T>
{
public static MyTaskMethodBuilder<T> Create()
{
return new();
}
private readonly MyTask<T> _task = new();
public MyTask<T> Task => _task;
public void SetException(Exception exception)
{
_task.SetException(exception);
}
public void SetResult(T result)
{
_task.SetResult(result);
}
public void AwaitOnCompleted<TAwaiter, TStateMachine>(
ref TAwaiter awaiter,
ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.OnCompleted(stateMachine.MoveNext);
}
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
ref TAwaiter awaiter,
ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
awaiter.UnsafeOnCompleted(stateMachine.MoveNext);
}
public void Start<TStateMachine>(
ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
public void SetStateMachine(
IAsyncStateMachine stateMachine)
{
// do nothing
}
}
partial class Program
{
class StateMachine :
IAsyncStateMachine
{
private readonly MyTaskMethodBuilder<int> _builder;
private int _state = 0;
private ConfiguredTaskAwaitable<int>.ConfiguredTaskAwaiter _awaiter1;
private ConfiguredTaskAwaitable.ConfiguredTaskAwaiter _awaiter2;
private ConfiguredTaskAwaitable<int>.ConfiguredTaskAwaiter _awaiter3;
private int _result;
public StateMachine(
MyTaskMethodBuilder<int> builder)
{
ArgumentNullException.ThrowIfNull(builder);
this._builder = builder;
}
void IAsyncStateMachine.MoveNext()
{
var builder = _builder;
try
{
int result;
ConfiguredTaskAwaitable<int>.ConfiguredTaskAwaiter awaiter1;
ConfiguredTaskAwaitable.ConfiguredTaskAwaiter awaiter2;
ConfiguredTaskAwaitable<int>.ConfiguredTaskAwaiter awaiter3;
switch (_state)
{
case 0:
result = 100;
awaiter1 = IncrementAsync(result, "step 1").ConfigureAwait(false).GetAwaiter();
if (!awaiter1.IsCompleted)
{
_state = 1;
_awaiter1 = awaiter1;
_result = result;
var stateMachine = this;
builder.AwaitUnsafeOnCompleted(ref awaiter1, ref stateMachine);
return;
}
step1_completed:
result = awaiter1.GetResult();
awaiter2 = Task.Delay(TimeSpan.FromSeconds(10)).ConfigureAwait(false).GetAwaiter();
if (!awaiter2.IsCompleted)
{
_state = 2;
_awaiter2 = awaiter2;
_result = result;
var stateMachine = this;
builder.AwaitUnsafeOnCompleted(ref awaiter2, ref stateMachine);
return;
}
step2_completed:
awaiter2.GetResult();
awaiter3 = IncrementAsync(result, "step 3").ConfigureAwait(false).GetAwaiter();
if (!awaiter3.IsCompleted)
{
_state = 3;
_awaiter3 = awaiter3;
_result = result;
var stateMachine = this;
builder.AwaitUnsafeOnCompleted(ref awaiter3, ref stateMachine);
return;
}
step3_completed:
goto final;
case 1:
awaiter1 = _awaiter1;
result = _result;
goto step1_completed;
case 2:
awaiter2 = _awaiter2;
result = _result;
goto step2_completed;
case 3:
awaiter3 = _awaiter3;
result = _result;
goto step3_completed;
final:
result = awaiter3.GetResult();
builder.SetResult(result);
return;
}
}
catch (Exception e)
{
builder.SetException(e);
}
}
void IAsyncStateMachine.SetStateMachine(
IAsyncStateMachine stateMachine)
{
// do nothing
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment