在JavaScript中模拟上下文切换?

时间:2011-02-07 06:58:11

标签: javascript multithreading context-switch

我一直致力于在JavaScript中实现一个非常复杂的系统,需要模拟多线程进程等。在真正的多线程进程(例如内核线程)中,可以通过上下文切换在线程之间切换。这是有效的,因为您可以存储当前进程的程序计数器并注册到临时结构,还原程序计数器并注册其他进程,然后在上一过程中从中断处继续。

我很好奇是否可以在JavaScript中使用类似的东西。我目前不知道这样做,所以一直在使用协作式多任务设计系统。特别是,我想在多线程模拟器中运行的任何“函数”被分成函数的数组。为了执行“函数”,我遍历函数数组,按顺序执行每个函数,同时保持接下来执行哪个函数的“程序计数器”。这允许我通过调用数组中的一个函数来模拟上下文切换,等待函数返回,然后切换到需要执行的其他函数数组。

我目前的方法有效,但在这个系统中编写代码很困难。每个函数必须具体指明它何时可以被中断,并且因为数组中的函数都是分开的,所以在函数的不同部分之间传递数据的逻辑是复杂的。我希望能够更接近先发制人的多任务工作。

我的问题是:是否可以通过外部来源暂停和恢复任意JavaScript功能?

2 个答案:

答案 0 :(得分:4)

检查StratifiedJS

答案 1 :(得分:3)

首先,重要的是要提到JavaScript是完全单线程的。模拟多线程真的不是可行的方法。你依靠eventloops好多了。

如前所述,可以使用网络工作者,但实际上并没有针对他们的跨浏览器合规性,所以我会忽略网络工作者。此外,您无法对Web worker进行任何DOM操作。

我想说看node.js来推断为什么事件循环是多线程的一个很好的替代品。我相信他很清楚为什么它在这个video中是一个很好的选择。

因此,有了一个函数数组并迭代它们,您可以创建一个事件并将一组函数绑定到它们并触发所述事件。可以在backbone.js中找到非常轻量级的事件实现。

你不能只在JavaScript中暂停一个线程,因为只有一个。如果函数中没有点,就无法暂停或恢复函数。

只有一种方法可以模仿。编写一个JavaScript解析器,将您精心构建的JavaScript分开,构建一个允许您暂停和恢复JavaScript的系统。

以此功能为例

function(i) {
    j = i + 1;
    console.log(j);
    return foo(j);
}

并将其转换为此

var bar = function(i) {
    var r = {};
    var j = i + 1; 
    var f = function() {
         console.log(j);
         var g = function() {
              return foo(j);
         };
         onNext(g, arguments.callee, this, r);
    };
    onNext(f, arguments.callee, this);
    return r;
}

您需要使用.suspend.resume

扩展功能
Function.prototype.suspend = function() {
     this.__suspended = true;
}

Function.prototype.resume = function() {
     this.__suspended = false;
}

function onNext(callback, function, context, returnObj) {
     if (!function.__suspended) {
          var cb = function() {
              Backbone.Events.unbind("run", cb);
              returnObj.r = callback.call(this);
          }
          Backbone.Events.bind("run", cb);
     }
}

setInterval(function() {
     Backbone.Events.trigger("run");
}, 5);

您还必须使用

替换var a = b()的所有引用
callFunctionAsync(b, context, args, function(return) {
    var a = return;
    ...
});

我会把实施留给你。现在,所有函数都返回一个对象r,并且只有当r.r设置为值时才会返回“返回”。因此,只需通过检查是否已设置r.r以及是否已触发函数异步回调来检查事件循环是否已“返回”。

嘿,看看我们得到了什么。通过围绕事件循环运行线程来模拟线程。在代码中本地使用事件循环而不是通过它模拟线程会更好。

当你再次绕过事件循环时,基本上让你的函数运行它的代码的下一行。当你绕过eventloop时,检查特定的“功能”是否被暂停或恢复。

为了简洁起见,我没有实现将函数返回冒泡回“函数”。这不应该太难模仿。

直接使用事件循环或使用伪线程方法并获取编译器来编译代码,以便在编码时看起来不可思议。

如果你造成死锁,祝你好运。