Search in sources :

Example 1 with CpsCallableInvocation

use of com.cloudbees.groovy.cps.impl.CpsCallableInvocation in project groovy-cps by cloudbees.

the class GreenThread method start.

/**
     * Creates a new green thread that executes the given closure.
     */
public void start() {
    Block b;
    try {
        run();
        // closure had run synchronously.
        b = Block.NOOP;
    } catch (CpsCallableInvocation inv) {
        // this will create a thread, and resume with the newly created thread
        b = inv.asBlock();
    } catch (Throwable t) {
        // closure had run synchronously and failed
        b = new ThrowBlock(new ConstantBlock(t));
    }
    final Block bb = b;
    invoke(new ThreadTask() {

        public Result eval(GreenWorld w) {
            w = w.withNewThread(new GreenThreadState(GreenThread.this, bb));
            return new Result(w, new Outcome(GreenThread.this, null), false);
        }
    });
    // thus the code will never reach here
    throw new AssertionError();
}
Also used : ThrowBlock(com.cloudbees.groovy.cps.impl.ThrowBlock) ConstantBlock(com.cloudbees.groovy.cps.impl.ConstantBlock) CpsCallableInvocation(com.cloudbees.groovy.cps.impl.CpsCallableInvocation) Outcome(com.cloudbees.groovy.cps.Outcome) Block(com.cloudbees.groovy.cps.Block) ConstantBlock(com.cloudbees.groovy.cps.impl.ConstantBlock) ThrowBlock(com.cloudbees.groovy.cps.impl.ThrowBlock)

Example 2 with CpsCallableInvocation

use of com.cloudbees.groovy.cps.impl.CpsCallableInvocation in project groovy-cps by cloudbees.

the class BasicTest method exceptionStackUnwinding.

/**
     * An exception thrown in a function caught by another function
     */
@Test
public void exceptionStackUnwinding() {
    class Op {

        /**
             * if (0<depth)
             *      throw_(depth-1,message);
             * else
             *      throw new IllegalArgumentException(message)
             */
        public void throw_(int depth, String message) {
            Block $depth = b.localVariable("depth");
            CpsFunction f = new CpsFunction(asList("depth", "message"), b.block(b.if_(b.lessThan(0, b.zero(), $depth), b.functionCall(0, b.this_(), "throw_", b.minus(0, $depth, b.one()), b.localVariable("message")), // else
            b.throw_(0, b.new_(0, IllegalArgumentException.class, b.localVariable("message"))))));
            throw new CpsCallableInvocation(f, this, depth, message);
        }
    }
    /*
            int x;
            try {
                x = 1;
                new Op().throw_(3,"hello")
                x = 2; // make sure this line gets skipped
            } catch (Exception e) {
                return e.message + x;
            }
         */
    assertEquals("hello1", run(// part of the test is to ensure this 'z' is separated from 'z' in the add function
    b.setLocalVariable(0, "x", b.zero()), b.tryCatch(b.block(b.setLocalVariable(0, "x", b.one()), b.functionCall(0, b.constant(new Op()), "throw_", b.constant(3), b.constant("hello")), b.setLocalVariable(0, "x", b.two())), null, new CatchExpression(Exception.class, "e", b.return_(b.plus(0, b.property(0, b.localVariable("e"), "message"), b.localVariable("x")))))));
}
Also used : CpsCallableInvocation(com.cloudbees.groovy.cps.impl.CpsCallableInvocation) CpsFunction(com.cloudbees.groovy.cps.impl.CpsFunction) InvocationTargetException(java.lang.reflect.InvocationTargetException) Test(org.junit.Test)

Example 3 with CpsCallableInvocation

use of com.cloudbees.groovy.cps.impl.CpsCallableInvocation in project groovy-cps by cloudbees.

the class Continuable method wrap.

private static Next wrap(Script s, Env env, Continuation k) {
    try {
        Method m = s.getClass().getMethod("run");
        if (!m.isAnnotationPresent(WorkflowTransformed.class))
            throw new IllegalArgumentException(s + " is not CPS-transformed");
        s.run();
        throw new AssertionError("I'm confused if Script is CPS-transformed or not!");
    } catch (CpsCallableInvocation e) {
        return e.invoke(env, null, k);
    } catch (NoSuchMethodException e) {
        throw new AssertionError(e);
    }
}
Also used : CpsCallableInvocation(com.cloudbees.groovy.cps.impl.CpsCallableInvocation) Method(java.lang.reflect.Method)

Example 4 with CpsCallableInvocation

use of com.cloudbees.groovy.cps.impl.CpsCallableInvocation in project workflow-cps-plugin by jenkinsci.

the class CpsBodyExecution method launch.

/**
 * Starts evaluating the body.
 *
 * If the body is a synchronous closure, this method evaluates the closure synchronously.
 * Otherwise, the body is asynchronous and the method schedules another thread to evaluate the body.
 *
 * @param currentThread
 *      The thread whose context the new thread will inherit.
 */
@CpsVmThreadOnly
/*package*/
void launch(CpsBodyInvoker params, CpsThread currentThread, FlowHead head) {
    if (isLaunched())
        throw new IllegalStateException("Already launched");
    StepStartNode sn = addBodyStartFlowNode(head);
    for (Action a : params.startNodeActions) {
        if (a != null)
            sn.addAction(a);
    }
    head.setNewHead(sn);
    CpsFlowExecution.maybeAutoPersistNode(sn);
    StepContext sc = new CpsBodySubContext(context, sn);
    for (BodyExecutionCallback c : callbacks) {
        c.onStart(sc);
    }
    try {
        // TODO: handle arguments to closure
        Object x = params.body.getBody(currentThread).call();
        // pointless synchronization to make findbugs happy. This is already done, so there's no cancelling this anyway.
        synchronized (this) {
            this.thread = currentThread;
        }
        onSuccess.receive(x);
    } catch (CpsCallableInvocation e) {
        // execute this closure asynchronously
        // TODO: does it make sense that the new thread shares the same head?
        CpsThread t = currentThread.group.addThread(createContinuable(currentThread, e), head, ContextVariableSet.from(currentThread.getContextVariables(), params.contextOverrides));
        // due to earlier cancellation
        synchronized (this) {
            t.resume(new Outcome(null, stopped));
            assert this.thread == null;
            this.thread = t;
        }
    } catch (Throwable t) {
        // body has completed synchronously and abnormally
        synchronized (this) {
            this.thread = currentThread;
        }
        onFailure.receive(t);
    }
}
Also used : ErrorAction(org.jenkinsci.plugins.workflow.actions.ErrorAction) Action(hudson.model.Action) BodyInvocationAction(org.jenkinsci.plugins.workflow.actions.BodyInvocationAction) StepStartNode(org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode) StepContext(org.jenkinsci.plugins.workflow.steps.StepContext) CpsCallableInvocation(com.cloudbees.groovy.cps.impl.CpsCallableInvocation) Outcome(com.cloudbees.groovy.cps.Outcome) BodyExecutionCallback(org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback)

Aggregations

CpsCallableInvocation (com.cloudbees.groovy.cps.impl.CpsCallableInvocation)4 Outcome (com.cloudbees.groovy.cps.Outcome)2 Block (com.cloudbees.groovy.cps.Block)1 ConstantBlock (com.cloudbees.groovy.cps.impl.ConstantBlock)1 CpsFunction (com.cloudbees.groovy.cps.impl.CpsFunction)1 ThrowBlock (com.cloudbees.groovy.cps.impl.ThrowBlock)1 Action (hudson.model.Action)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 BodyInvocationAction (org.jenkinsci.plugins.workflow.actions.BodyInvocationAction)1 ErrorAction (org.jenkinsci.plugins.workflow.actions.ErrorAction)1 StepStartNode (org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode)1 BodyExecutionCallback (org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback)1 StepContext (org.jenkinsci.plugins.workflow.steps.StepContext)1 Test (org.junit.Test)1