Discussions

News: Sam Ruby on Continuations for Curmudgeons

  1. Sam Ruby on Continuations for Curmudgeons (16 messages)

    Sam Ruby has written a document called "Continuations for Curmudgeons" on what continuations are, for those of us who aren't familiar with them, and how they can be used, along with some drawbacks.

    Basically, continuations are preserved points of execution, such that you can resume execution of a process preserving its state. In C, they can be thought of as being implemented by setjmp() and longjmp(), among other things.

    Continuations don't apply only to programming, but to design, as Use Continuations to develop complex Web applications shows, and such constructs are often referred to as some of the advantages that some scripting languages have over Java.

    Continuations aren't part of Java itself: would you use them if they were? Where? What do you think about the use of continuations in general?

    Threaded Messages (16)

  2. Some Java based initiatives :

    http://docs.codehaus.org/display/continuation/Home
    http://jakarta.apache.org/commons/sandbox/javaflow/

    Also, there is a recent discussion about continuations implementations in Spring Web Flow and Rife here.

    So there are people trying to see continuation at JVM level and others doing it already for specific use cases, mainly web flows.

    From DeveloperWorks article:
    A second big hurdle is that of how and where to store continuations... We can also store them on the server side, which is what I did in the sample application, but then we have to worry about issues like garbage collection and replication across cluster nodes...

    In my opinion, this is not a really a big issue nowadays since we could classify the continuation "stack" to be saved as a transient data. Cameron P., the way is now clear to you here ;)

    An for continuations at JVM level, I think is too simplistic to say we need JUST continuations. THe impact of doing this is sufficient to consider a lot of other aspects and do a rework of core aspects of current JVM. Consider this, for example. Not to mention JVM issues at client side, where we do have some non standard but interesting attempts to provide solutions like this.

    Humm, I forgot to say: I like continuations.
  3. An for continuations at JVM level, I think is too simplistic to say we need JUST continuations.

    I meant we do have to think in a broader context since any new feature can have a very negative impact to some other existent or important future feature, after all JVM is too critical to all Java industry. So then perhaps we could realize this is simply unrealistic to ask today (new feature x or y in core JVM).
  4. Continuations in Cocoon[ Go to top ]

    Sam mentions Cocoon but doesn't provide much of an example. Here is one from the Cocoon web site. Advanced Control Flow.
  5. Continuations in RIFE[ Go to top ]

    In RIFE (similarly to Cocoon) we have adopted a continuations style that doesn't mandate their use throughout the whole web engine (which is what Seaside does iirc). There are a number of situations where continuations make your life easier, however there are even more situations where they don't feel natural in a web application. The solution continuations solve best is one where you have a multi-step 'island of functionality' that does one particular thing on its own and that shouldn't be committed to the backend before the final step is finished. These are typically a wizard, a game, a multi-page admin intervention, a survey, ...

    You can find a presentation about RIFE continuations at java.net. For more information, feel free to browse some sources or read our wiki pages about it.
  6. Some Java based initiatives..

    It would be possible for Java to support language-level continuations with a special sub-class of Throwable, e.g. Continuable. The "yield" equivalent would be to construct the continuable object, which would capture the current frame state (on up the chain of execution frames), throw the object, and let it get caught by an outer frame that is expecting the object to be thrown. A method on the continuable object would allow continuation to be triggered, re-assembling the necessary frames, etc.

    The question as to the runtime cost .. no idea on that one.

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Cluster your POJOs!
  7. Some Java based initiatives..
    It would be possible for Java to support language-level continuations with a special sub-class of Throwable, e.g. Continuable. The "yield" equivalent would be to construct the continuable object, which would capture the current frame state (on up the chain of execution frames), throw the object, and let it get caught by an outer frame that is expecting the object to be thrown. A method on the continuable object would allow continuation to be triggered, re-assembling the necessary frames, etc.The question as to the runtime cost .. no idea on that one.

    This is very similar to how it's done in RIFE. For the assembling, bytecode modification is needed though since you can't introspect the local variable stack. To reassemble, the only way is to jump through the code again, starting from a known entry point and skipping all parts that have already been executed.
  8. Thread base implementation[ Go to top ]

    Look at the comment I posted (http://www.intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons) on his blog... I provide a simple way to do it in Java by using a thread to keep the continuation stack frame.

    This is proof of concept level... An it does not address the eventual pesistence of the stack frame.
  9. Thread base implementation[ Go to top ]

    Thread-based implementation can't work in a web environment since you typically hijack the thread and it can't be used by other users anymore. For performance and scalability reasons, threads have to be released as soon as a request terminates.
  10. Thread base implementation[ Go to top ]

    Did you check the code?

    The continuation stack frame is kept in a new thread... It will not consume and/or block any thread responding to a request.

    The only time the request thread will block is when calling the continuation doit() method. And it will block until the continuation calls the yield() method or when it's execute() method exits (however, there is a bug the sample... If the execute method returns normally (without a yield()), it's returned value will not be returned by the doit() method). This is no more different than the thread method calling some ordinary method in an ordinary object.

    The example is fairly simple and was done in less than 30 minutes. But it does prove that continuation can be done without relying on new features in the VM. The only thing that this proof of concept lack is that the continuation stack frame cannot be serialized because a thead cannot be serialized. Only attribute of the continuation could be serialized.

    This mean that you cannot easily provide failover of continuation based on thread on a cluster without some other mechanism (think bytecode manipulation).

    Other than that, this demonstration is entirely fit for a web application.
  11. Thread base implementation[ Go to top ]

    You're right, Emmmanuel, I'm sorry, I didn't read your code and jumped to conclusions. The real difficulty with implementing native Java continuations is to make them work without changing any code and simply adding a simple statement (pause()) in RIFE. The execution stack and local variable stack needs to be retrieved automatically at that point it time and later restored. The JVM can't do this as of now.

    Your implementation requires changing the code by extending a Continuation thread class which spawns a new thread each time it's used, but that could be acceptable. However, in a web application there are also other needs, like the possibility to use the back/forward button and the obtain the continuation that was active at that particular point. This means that you need to start cloning or serializing continuations contexts and keep track of which one to use where. I don't think Java can clone thread instances in wait state with the complete local variable stack and execution frames. So the need of thread serialization is not only there for failover.

    What you in fact implemented is a solution for only the latest continuation in a continuation tree, each previous continuation in the tree is lost when you go to the next, while normally continuations allow you to keep the whole tree available and reuse any continuation of it. Taking the quote from the developerworks article: "A continuation is a saved snapshot of the executable state of a program at any given point in time. It is possible to restore this state and restart the execution of the program from that point onward, such that the stack trace, all the local variables, and the program counter can reclaim their old values."
    Your implementation doesn't take care of the 'saved' (but you said that yourself already).
  12. Thread base implementation[ Go to top ]

    is this not just over complex, twisting the language to support a 'yield' keyword it doesn't have ?

    The fib could be implemented like this :
    private static Continuation fib= new Continuation() {
    private int i=0;
                    private int j=1;
    public Object doIt() {
                              int tmp=j;
    i= j; j= i+j;
                              return new Integer(tmp);
    }
    }

    };

    The thread doesn't give anything to the solution. You're using the heap to store state (i,j), inside the object itself, not inside the frame.
  13. Still not quite convinced[ Go to top ]

    I posted a few thoughts (and doubts) on my blog:

    http://beust.com/weblog/archives/000272.html

    Somebody pointed out in the comments that despite what the article says, C# doesn't support continuations, only closures. The "yield" keywords certainly adds to the confusion.

    --
    Cedric
  14. RE: Still not quite convinced[ Go to top ]

    As a reply to Cedric's post I recorded a video to show that continuations can be debugged with a regular Java debugger when using the RIFE framework, which offers native web continuations in Java.

    http://rifers.org/blogs/gbevin/2005/4/18/debugging_continuations_in_rife
  15. Thread base implementation[ Go to top ]

    is this not just over complex, twisting the language to support a 'yield' keyword it doesn't have ? The fib could be implemented like this :private static Continuation fib= new Continuation() { private int i=0;                private int j=1; public Object doIt() {                          int tmp=j; i= j; j= i+j;                          return new Integer(tmp); } } };The thread doesn't give anything to the solution. You're using the heap to store state (i,j), inside the object itself, not inside the frame.

    You are absolutely right... The fib function need not to be implemented with a continuation (as Cedric pointed out in his blog, this function is a bad example for the use of continuation).

    I just used it in my example because I just wanted to show that it was possible to do it with code very much like the example from Sam Ruby's column (in fact the fib function is almost identical).

    However, if the work you need to do between each yield() is different, then my implementation has it's uses.

    It does have it's drawbacks too... Using thread just to store a stackframe consume a non negligeable amount of system resources... While these threads will be sleeping most of the time, it does put some load on the OS scheduler. And it may not scale all that well after a few thousands threads. So it's not very appropriate for an application that must support a lot of concurrent users.

    Please do remember, that I did that in less time than the time I spent replying to comments in this thread... And it is just a proof of concept. I very doubt that I will use that in a real application. I just had fun doing it.
  16. I remember this being implemented in an agent framework
    around 97/98 with above "keywords".

    Basically a program would throw an Exception on go() and
    upon reactivation the framework "walked" the methods up
    (doing nothing) to the point of interruption.
    Incredible hack but impossible to trigger "continuation"
    externally...

    The Glasgow project (rejected Jsr20) started with
    similar goals (on VM level)
  17. Some Java based initiatives..
    It would be possible for Java to support language-level continuations with a special sub-class of Throwable, e.g. Continuable. The "yield" equivalent would be to construct the continuable object, which would capture the current frame state (on up the chain of execution frames), throw the object, and let it get caught by an outer frame that is expecting the object to be thrown. A method on the continuable object would allow continuation to be triggered, re-assembling the necessary frames, etc.The question as to the runtime cost .. no idea on that one.Peace,Cameron PurdyTangosol, Inc.Coherence: Cluster your POJOs!

    Don Box has an awesome follow up:
    http://pluralsight.com/blogs/dbox/archive/2005/04/17/7467.aspx