Skip to content

Instantly share code, notes, and snippets.

@mfakane
Created September 20, 2011 21:44
Show Gist options
  • Save mfakane/1230495 to your computer and use it in GitHub Desktop.
Save mfakane/1230495 to your computer and use it in GitHub Desktop.
Async CTP の async/await による coroutine の簡易実装
using System;
using System.Reactive.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var ctx = new CoroutineContext<int>();
A(ctx);
for (var i = 0; ; i++)
{
ctx.MoveNext(i);
Console.ReadKey(true); // press any key
}
}
// coroutine
static async void A(CoroutineContext<int> ctx)
{
while (true)
Console.WriteLine(await ctx.Yield());
}
}
public class CoroutineContext<T>
{
event Action<T> Dispatch;
public Awaitable<Awaiter> Yield()
{
return Awaitable.Create(() => new Awaiter(this, _ => _));
}
public Awaitable<Awaiter> Yield(int times)
{
return Awaitable.Create(() => new Awaiter(this, _ => _.Skip(times - 1)));
}
public Awaitable<Awaiter> YieldWhile(Func<T, bool> condition)
{
return Awaitable.Create(() => new Awaiter(this, _ => _.SkipWhile(condition)));
}
public void MoveNext(T arg)
{
if (Dispatch != null)
Dispatch(arg);
}
public class Awaiter
{
readonly CoroutineContext<T> context;
readonly Func<IObservable<T>, IObservable<T>> let;
T value;
public Awaiter(CoroutineContext<T> context, Func<IObservable<T>, IObservable<T>> let)
{
this.context = context;
this.let = let;
}
public bool IsCompleted
{
get
{
return false;
}
}
public void OnCompleted(Action continuation)
{
Observable.FromEvent<T>(_ => context.Dispatch += _, _ => context.Dispatch -= _)
.Let(let)
.Take(1)
.Do(_ => value = _)
.Subscribe(_ => continuation());
}
public T GetResult()
{
return value;
}
}
}
public static class Awaitable
{
public static Awaitable<T> Create<T>(Func<T> generator)
{
return new Awaitable<T>(generator);
}
}
public class Awaitable<T>
{
readonly Func<T> generator;
public Awaitable(Func<T> generator)
{
this.generator = generator;
}
public T GetAwaiter()
{
return generator();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment