package extra; import static avian.Continuations.callWithCurrentContinuation; import avian.Function; import avian.Callback; public class Coroutines { private static void expect(boolean v) { if (! v) throw new RuntimeException(); } private static void produce(Consumer consumer) throws Exception { System.out.println("produce \"a\""); consumer.consume('a'); System.out.println("produce \"b\""); consumer.consume('b'); System.out.println("produce \"c\""); consumer.consume('c'); } private static void consume(Producer producer) throws Exception { char v = producer.produce(); System.out.println("consume \"" + v + "\""); expect(v == 'a'); v = producer.produce(); System.out.println("consume \"" + v + "\""); expect(v == 'b'); v = producer.produce(); System.out.println("consume \"" + v + "\""); expect(v == 'c'); } public static void main(String[] args) throws Exception { final CoroutineState state = new CoroutineState(); final Consumer consumer = new Consumer() { public void consume(final Character c) throws Exception { callWithCurrentContinuation(new Function,Object>() { public Object call(Callback continuation) { state.produceNext = continuation; state.consumeNext.handleResult(c); throw new AssertionError(); } }); } }; final Producer producer = new Producer() { final Function,Character> receiver = new Function,Character>() { public Character call(Callback continuation) throws Exception { state.consumeNext = continuation; if (state.produceNext == null) { Coroutines.produce(consumer); } else { state.produceNext.handleResult(null); } throw new AssertionError(); } }; public Character produce() throws Exception { return callWithCurrentContinuation(receiver); } }; consume(producer); } private static class CoroutineState { public Callback produceNext; public Callback consumeNext; } private interface Producer { public T produce() throws Exception; } private interface Consumer { public void consume(T value) throws Exception; } }