cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Christopher Oliver <res1c...@verizon.net>
Subject Re: Groovy support in Cocoon
Date Mon, 05 Apr 2004 17:18:26 GMT
After thinking about this a few more minutes over coffee, I like the 
idea of constructing the continuation stack as the JVM stack is unwound 
(that way "normal" code doesn't encounter any overhead other than the 
tests for isRestoring() and isCapturing(). So perhaps what we could do 
when Continuation.getCurrentContinuation() is called is to unwind the 
JVM stack, constructing the continuation stack, and then immediately 
restore it returning the newly created continuation object (which will 
contain a copy of the continuation stack we just created). If the 
continuation object is invoked we will again unwind the current JVM 
stack, but this time there's no need to capture it.

Chris


Christopher Oliver wrote:

> Stephan Michels wrote:
>
>> Am Mo, den 05.04.2004 schrieb Christopher Oliver um 4:42:
>>  
>>
>>> The current implementation needs some work to qualify as 
>>> "generalized Java continuations". It would be nice to make it work 
>>> more like Scheme continuations:
>>>
>>> 1) When you access the "current" continuation, it captures the call 
>>> stack up to but not including the current method (and makes a 
>>> (shallow) copy of it). The current method continues as normal.   
>>
>>
>> What to you mean with "continues as normal". The current impl. stops the
>> execution of the method with null as return value, if the cuntinuation
>> is suspended. Then the continuation captures the object of the method
>> call and the current frame.
>>  
>>
> OK, IIUC there are three modes of execution of the instrumented code:
>
> 1) isCapturing
> During this mode the JVM call stack is unwound and its state captured 
> in the continuation call stack.
> 2) isRestoring
> During this mode a saved call stack in a continuation is recreated on 
> the JVM stack.
> 3) !isCapturing && !isRestoring
> This is the "normal" execution of the JVM  - no modifications are made 
> to the JVM call stack or to the continuation call stack.
>
> This is achieved by inserting code before each invoke instruction to 
> copy local variables from the continuation stack to the JVM stack and 
> to reset the program counter to the value saved in the continuation 
> stack if "isRestoring" is true, and by inserting code after each 
> invoke instruction to copy the values of local variables from the JVM 
> call stack as well as the program counter into the continuation call 
> stack if "isCapturing" is true.
>
> To make continuations more "Scheme-like" it must be possible to 
> construct a continuation without modifying the JVM call stack (thus 
> the current method invocation can "continue as normal").
>
> To make this possible the byte-code transformer could work like this:
>
> 1) Insert code before an invoke instruction to push local vars and the 
> pc onto the continuation stack if (!isRestoring && !isCapturing)
> 2) Insert code after an invoke instruction to pop those values from 
> the continuation stack if (!isRestoring && !isCapturing)
> 3) If (isRestoring == true) the pre-invoke code would work as it does 
> now.
> 4) If (isCapturing == true) the post-invoke code would simply cause 
> the current method invocation to return to its caller without 
> modifying the continuation stack - since it is already set up from 
> (1). When the JVM stack is completely unwound another continuation 
> will take the place of this one and that new continuation would be in 
> "isRestoring" mode until it is recreated on the JVM stack at which 
> point it would enter (!isRestoring && !isCapturing) mode.
>
> The user interface to this might look something like this:
>
> public class Continuation {
>        // Empty continuation for use as an escape procedure
>        public static final Continuation SUICIDE;
>
>        // Invoke a captured continuation - it will replace the current 
> continuation. I.e. the current JVM call stack will be unwound, the 
> call stack saved in this object will be recreated on the JVM call 
> stack, and the method invocation in which this object was created will 
> return with "returnValue".
>        public void invoke(Object returnValue);
>        // Get the current continuation -
>        public static Continuation getCurrentContinuation();
>        // Entry point to the instrumented code (precondition: cannot 
> be called recursively and method.getDeclaringClass() must be 
> instrumented)
>        public static Object invoke(Object obj, Method method, Object[] 
> args);
> }
>
>
> Below is some pseudo-code that shows how this would work with Cocoon:
>
> public class JavaInterpreter {
>        // ...
>        public void callFunction(String function, List params, 
> Redirector redirector)
>            throws Exception {
>            if (!initialized)
>                initialize();
>
>            Method method = (Method) methods.get(function);
>            Request request = 
> ContextHelper.getRequest(this.avalonContext);
>            Session session = request.getSession(true);
>            HashMap userScopes = (HashMap) 
> session.getAttribute(USER_GLOBAL_SCOPE);
>            if (userScopes == null)
>               userScopes = new HashMap();
>
>            Object flow = (Object) 
> userScopes.get(method.getDeclaringClass());
>
>            if (flow == null) {
>                if (getLogger().isDebugEnabled())
>                   getLogger().debug("create new instance of 
> \""+method.getDeclaringClass()+"\"");
>
>            flow =  method.getDeclaringClass().newInstance();
>            userScopes.put(method.getDeclaringClass(), flow);
>            int size = params == null ? 0 : params.size();
>            Object[] args = new Object[size];
>            for (int i = 0; i < size; i++) {
>                    Interpreter.Argument arg = 
> (Interpreter.Argument)params.get(i);
>                    args[i] = arg.value;
>            }
>            Continuation.invoke(flow, method, args);
>        }
>
>        public void handleContinuation(String id, List params, 
> Redirector redirector)
>            throws Exception {
>            if (!initialized)
>                initialize();
>
>            WebContinuation wk = 
> continuationsMgr.lookupWebContinuation(id);
>            Continuation k = (Continuation) wk.getContinuation();
>             k.invoke(wk);
>         }
>
> }
>
> public class Cocoon {
>     // ...
>     public WebContinuation sendPageAndWait(String uri, Object biz, 
> long ttl) {
>              Continuation kont = Continuation.getCurrentContinuation();
>              WebContinuation wk = 
> continuationsMgr.createWebContinuation(kont,
>                                           parentWebContinuation,
>                                           ttl,
>                                           null);
>               sendPage(uri, biz);
>               Continuation.SUICIDE.invoke(null);
>               return wk; // never reached
>     }
>
>      public void sendPage(String uri, Object biz) {
>           // ...
>      }
> }
>
>
> Chris
>


Mime
View raw message