2011-02-07 3 views
7

Я работаю над реализацией довольно сложной системы в JavaScript, которая должна имитировать, помимо прочего, многопоточные процессы. В реальном многопоточном процессе (таком как поток ядра) можно переключаться между потоками посредством контекстного переключения. Это работает, потому что вы можете хранить счетчик программ текущего процесса и регистрироваться во временную структуру, восстанавливать счетчик программ и регистрировать какой-либо другой процесс, а затем возобновлять работу, в которой вы остановились в предыдущем процессе.Имитация контекстных переключателей в JavaScript?

Мне любопытно, есть ли в JavaScript что-то похожее на это. В настоящее время я не знаю, как это сделать, и поэтому мы разрабатываем систему с использованием совместной многозадачности. В частности, любая «функция», которую я хочу запустить в многопоточном симуляторе, разделяется на массив функций. Чтобы выполнить «функцию», я перебираю массив функций, выполняя каждый по порядку, сохраняя при этом «счетчик программ», из которого следует выполнить следующую функцию. Это позволяет мне моделировать контекстный переключатель, вызывая одну из функций в массиве, ожидая возвращения функции, а затем переключаясь на другой массив функций, которые необходимо выполнить.

Мой текущий подход работает, но в этой системе сложно писать код. Каждая функция должна указывать конкретно, когда ее можно прервать, и поскольку функции в массиве все раздельны, логика для передачи данных между различными частями функции сложна. Я надеялся получить что-то ближе к превентивной многозадачности, работающей вместо этого.

Мой вопрос: Можно ли запустить произвольную функцию JavaScript так, чтобы ее можно было приостановить и возобновить внешним источником?

+3

Обязательное упоминание о [Веб-работниках] (https://developer.mozilla.org/En/Using_web_workers), когда кто-то использует JavaScript и многопоточность в том же предложении. –

ответ

4

Проверить StratifiedJS из

+1

stratifiedjs.org говорит: «StratifiedJS расширяет язык JavaScript с помощью небольшого количества ключевых слов для параллельного программирования, что позволяет вам выражать асинхронный поток управления в прямом, структурированном последовательном стиле». Похоже на то, что вам нужно – tomg

+0

@ qwertymk- Это выглядит великолепно, но, к сожалению (из того, что я могу сказать), он не поддерживается никакими веб-браузерами, что несколько поражает цель. Это отличная ссылка, и я благодарю вас за то, что поделился ею! – templatetypedef

+0

@templatetypedef поддерживается веб-браузерами. Перейдите в [их консоль] (http://onilabs.com/docs#tryit) и попробуйте запустить это: 'console.log ('waiting 3 seconds ....'); держать (3000); console.log ('done') ' – qwertymk

3

Во-первых, важно отметить, что JavaScript является полностью однопоточный. Эмуляция многопоточности на самом деле не путь. Вам гораздо лучше полагаться на eventloops.

Как упоминалось, веб-работники могут использоваться, но для них не существует соответствия между браузерами, поэтому я буду игнорировать веб-работников. Также вы не можете манипулировать 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.

Я не реализовал возврат функций обратно к «функции» для краткости. Это не должно быть слишком сложно подражать.

Либо используйте цикл событий напрямую, либо используйте поддельные поточные методы и получите компилятор для компиляции кода, чтобы он не выглядел отвратительным при его кодировании.

Если вы причинили вам мертвые замки.

+0

@ Raynos- Спасибо за предложения! Моя текущая реализация на самом деле не использует потоки столько, сколько реализует систему, которая требует потоковой обработки (в частности, JVM), поэтому у меня действительно нет выбора здесь. В настоящее время я использую события для этого - у меня есть тайм-аут окна, который периодически срабатывает, чтобы запустить больше кода. Ваше предложение о том, что каждая функция зарегистрирует продолжение, действительно великолепна - я думаю, что я мог бы построить кросс-компилятор, который автоматически генерирует этот код для меня. Большое спасибо за ваш совет! – templatetypedef

+0

@templatetypedef Если ваша внедряющая threading для JVM для чего вам нужен ваш javascript для потоковой передачи? Вы позволяете пользователям запускать javascript-код поверх вашей JVM? Кажется настолько неправильным сделать это таким образом, и его действительно легко получить потоки неправильно и полностью разбить состояние.Любые внутренние компоненты JVM, которые требуют потоковой обработки, могут быть реализованы внутри вашего javascript с использованием циклов событий. – Raynos

+0

@ Raynos. Это наоборот. Я использую JavaScript для реализации JVM. :-) Это для академического проекта. Задача состоит в том, как наилучшим образом реализовать потоки уровня JVM внутри JavaScript, а также позволить встроенные функции Java внедряться изначально в JavaScript. – templatetypedef

Смежные вопросы