Comments inlined: Le 31/07/2009 14:40, Lukas Stadler a écrit : > Hi everybody! > > It's been a while since I posted the last update about the continuations > work: > > As Christian already mentioned we wrote a paper about the implementation > of the continuation capture/resume functionality. The paper isn't > published yet but I can send private copies to anyone who's interested. > I'll also attend the JVM Language Summit in September. > > Apart from the finishing the paper I've been working hard on making the > continuations patch more stable and I've by now created a small > junit-suite which allows me to perform all the refactorings I wanted to > do for such a long time... > The current API is quite simple: > > Continuation c = new Continuation(); > Object ret = c.save(); > if (ret == Continuation.CAPTURED) { > c.resume(null); > } > // ret is null at this point >
What's happen if i call resume() without calling save() ?? > The next thing on my agenda is delimited continuations. (which also > allows for portable, serializable, etc. continuations, you know, all the > fun stuff...) The challenge here isn't the technical implementation (as > this is already laid out by the underlying implementation) but the > interface. I'd be more than happy about any input you can give me! > > As I see it the basic problem is how one can specify the point at which > the continuation is bisected. There are a few options: > * use a (native or non-native) method that takes a Runnable as the border > * specify a method at which to cut the delimited continuation > * allow the application to walk the stackframes of the continuation and > decide where to cut > * use the "difference" between two continuations > * and possibly some more... > > For performance reasons there is one restriction: The delimited > continuation should not be cut within a stackframe. This might not seem > like a problem but remember that inline can collapse multiple java > stackframes into a single native one. > > So I'd propose the following: > > interface DelimitedRunnable { > public void run(Continuation cont); > } > > /* Executes runnable and passes the continuation that can be used to > return to return as a parameter. Every continuation stored below this > stackframe is a delimited continuation as soon as control returns to the > delimited method. */ > Object delimited(DelimitedRunnable runnable); > > /* Appends the delimited continuation to the current stack and starts > execution. The Continuation.copy method returns the continuation that > can be used to return. */ > Object delimited(Continuation cont); > Using overloading for methods with different semantics is a way to create puzzlers. > usage would look like this: > > class Enumerable implements DelimitedRunnable { > private Continuation cont = new Continuation(); > public void run(Continuation ret) { > int i = 0; > while (true) { > Object o = cont.save(); > if (o == Continuation.CAPTURED) > ret.resume(i); > else > ret = o; > i++; > } > } > > public void next() { > if (cont.isEmpty()) > Continuation.delimited(this); > else > Continuation.delimited(cont); > } > } > > Security: I don't think that delimited continuations make any difference > security-wise. > The current status: I could push the patch into the patch-repository, > but I'm kind of a mercurial-newbie... Do you perhaps have any pointers > to a description of how that works? :-) > > - Lukas > I like the Fiber API of Ruby 1.9, translated in Java: public class Fiber { public Fiber(Runnable r) { .... } // or save, suspend, passivate, etc public static void yield(Object value) { ... } public Object resume() { ... } } I think it's important to use a Runnable without argument because it better fit with current API but there is a mismatch: Runnable/Callable are used for asynchronous call (Thread or executor), I don't think it's a good idea to reuse the same interface for synchronous and asynchronous block of code. A first call to resume() run the runnable and it ends when resume() returns a sentinel. I think it's better than to have two different methods. I have declared yield (equivalent of save()) static because it avoid the user to call yield on another continuation. I don't know if with the current continuation is something that can be implemented easily or not. And the Fibonacci example (you can't post something a little bit serious without a Fibonacci example :) Fiber f = new Fiber(new RunnableOrAnotherInterface() { public void run() { int f = 1; int oldf =0; for(;;) { int fib = oldf + f; Fiber.yield(fib); oldf = f; f = fib; } } }); ... for(int i=0;i <10; i++) { System.out.println(f.resume()); } cheers, Rémi _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev