【问题标题】:Is it possible to resume a continuation in Rhino multiple times?是否可以多次在 Rhino 中恢复延续?
【发布时间】:2017-04-26 04:56:38
【问题描述】:

我希望能够捕获一个延续并多次恢复它,这样每个这样的调用都将独立于其他调用。

例如,在以下代码中,我希望在 run 方法中对 context.resumeContinuation 的 2 次调用产生输出:1 1,而不是 1 2 的当前输出。

据我了解,产生输出的原因是我始终使用相同的 scope 对象,该对象在传递给第二个延续之前由第一个延续进行修改。因此,我似乎应该使用原始scope副本 来恢复每个延续,但类型Scriptable 没有clone 方法(或任何等效方法),并使用序列化/反序列化复制它也无济于事。

P.S.我使用的是 Rhino 1.7R5 版本。

Example.java

import org.mozilla.javascript.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Example {
    public void run() throws IOException {
        Context context = Context.enter();
        context.setOptimizationLevel(-2);   // Use interpreter mode.
        Scriptable scope = context.initStandardObjects();
        scope.put("javaProxy", scope, Context.javaToJS(this, scope));

        Object capturedContinuation = null;
        try {
            String scriptSource =
                new String(Files.readAllBytes(Paths.get("example.js")));

            String scriptName = "example";
            int startLine = 1;
            Object securityDomain = null;
            Script script =
                context.compileString(scriptSource, scriptName, startLine, securityDomain);
            context.executeScriptWithContinuations(script, scope);
        } catch (ContinuationPending continuationPending) {
            capturedContinuation = continuationPending.getContinuation();
        }

        Object result = "";

        context.resumeContinuation(capturedContinuation, scope, result);
        context.resumeContinuation(capturedContinuation, scope, result);

        Context.exit();
    }

    public void captureContinuation() {
        Context context = Context.enter();
        ContinuationPending continuationPending =
            context.captureContinuation();
        Context.exit();
        throw continuationPending;
    }

    public void print(int i) {
        System.out.print(i + " ");
    }

    public static void main(String[] args) throws IOException {
        new Example().run();
    }
}

example.js

var i = 1;
javaProxy.captureContinuation();
javaProxy.print(i);
i = i + 1;

【问题讨论】:

    标签: java rhino continuations


    【解决方案1】:

    所以我想出了一个可行的解决方案:

    我应该复制capturedContinuation 对象,而不是复制scope 对象,所以对resumeContinuation 的两次调用将是:

    context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
    context.resumeContinuation(deepCopy(capturedContinuation), scope, result);
    

    This question 提供了deepCopy 方法的可能实现。

    但请注意:Rhino 的 NativeContinuation 类型(上面代码中 capturedContinuation 的动态类型)的实例似乎非常大(序列化为字节数组时约为 15KB 及以上),因此在应用程序中进行深度复制时应考虑时间/内存消耗问题。

    【讨论】:

      【解决方案2】:

      这只是一个猜测,但我认为这可能有效(Rhino 1.7.6):

          NativeContinuation capturedContinuation = ...
          final Object stackFrame = capturedContinuation.getImplementation();
      
          // Invoke once...
          context.resumeContinuation(capturedContinuation, scope, result);
      
          // Put stack back where it was
          capturedContinuation.initImplementation(stackFrame);
      
          // Invoke twice...
          context.resumeContinuation(capturedContinuation, scope, result);
      

      【讨论】:

        猜你喜欢
        • 2020-06-20
        • 1970-01-01
        • 1970-01-01
        • 2015-05-26
        • 2020-06-02
        • 1970-01-01
        • 2016-03-16
        • 2019-03-15
        • 2021-12-06
        相关资源
        最近更新 更多