/** * Declares an intent to release control to another thread in the future, or performs the actual * release now. The behaviour depends on whether a method has been invoked on the control object. * (See {@link #object}.) If it has, then the release is scheduled when the position represented * by the control call has been reached, and the state of the control object is cleared. * Otherwise, the release is performed immediately. * * <p>Releasing control will block this script, and allow the released script to start, or to * resume execution. This script will remain blocked until another script releases control back to * it, or until the first Script belonging to the {@link Scripter} is released. * * <p>Note that it is only possible to release to another Script that is being run by the same * {@link Scripter}. */ public void releaseTo(Script<T> other) { if (this == other) { throw new IllegalArgumentException("Cannot release control to the same script"); } if (!running()) { // If we're not running, then we must be scheduling a future // release. (Calling recorder.position() will throw an // IllegalStateException if a valid position has not been specified, so no // need to check here. // futureTargets.add(new ScriptTarget<T>(recorder.position(), other)); } else { // If the scripter has been set, then we are either releasing control or // preparing to do so, depending on whether a position has been specified. CodePosition cp = recorder.getPositionIfAny(); if (cp == null) { doRelease(other); } else { Breakpoint breakPoint = getInstrumentedObject().createBreakpoint(cp, thread); breakPoint.setHandler(new ReleasingHandler(other)); synchronized (breakPoints) { breakPoints.add(breakPoint); } } } }
/** * Prepares this ScriptedThread to be executed by the given scripter in the given thread. Creates * Breakpoints for all of the release positions that have been predefined. This method is invoked * by the owning Scripter before calling {@link #runTasks}. */ void prepare(Scripter<T> theScripter, TestThread theThread) { this.scripter = theScripter; ObjectInstrumentation<T> instrumented = getInstrumentedObject(); breakPoints = new ArrayList<Breakpoint>(futureTargets.size()); for (ScriptTarget<T> target : futureTargets) { Breakpoint breakPoint = instrumented.createBreakpoint(target.codePosition, theThread); breakPoint.setHandler(new ReleasingHandler(target.script)); breakPoints.add(breakPoint); } this.thread = theThread; }