summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2012-01-06 00:42:10 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2012-01-06 00:47:14 +0100
commit42281124d4b83b0e99baf5d56b696ef242399f51 (patch)
tree62b332b31358dd80f884167ac868c77dd4ca6243
parent1e73e4c62f14e8c68c284b20fd754523af63f157 (diff)
downloadnode-42281124d4b83b0e99baf5d56b696ef242399f51.tar.gz
child_process: add isolates support
Passing an options object with {thread:true} to .fork() or .spawn() will run the target script in a thread instead of a separate process.
-rw-r--r--lib/child_process.js64
-rw-r--r--src/node.js15
2 files changed, 70 insertions, 9 deletions
diff --git a/lib/child_process.js b/lib/child_process.js
index 2e3916660..5a3374cda 100644
--- a/lib/child_process.js
+++ b/lib/child_process.js
@@ -167,12 +167,6 @@ exports.fork = function(modulePath, args, options) {
args = args ? args.slice(0) : [];
args.unshift(modulePath);
- if (options.thread) {
- if (!process.features.isolates) {
- throw new Error('node compiled without isolate support');
- }
- }
-
if (options.stdinStream) {
throw new Error('stdinStream not allowed for fork()');
}
@@ -191,11 +185,11 @@ exports.fork = function(modulePath, args, options) {
options.env.NODE_CHANNEL_FD = 42;
// stdin is the IPC channel.
- options.stdinStream = createPipe(true);
+ if (!options.thread) options.stdinStream = createPipe(true);
var child = spawn(process.execPath, args, options);
- setupChannel(child, options.stdinStream);
+ if (!options.thread) setupChannel(child, options.stdinStream);
child.on('exit', function() {
if (child._channel) {
@@ -358,7 +352,7 @@ var spawn = exports.spawn = function(file, args, options) {
envPairs.push(key + '=' + env[key]);
}
- var child = new ChildProcess();
+ var child = (options && options.thread) ? (new Isolate) : (new ChildProcess);
child.spawn({
file: file,
@@ -520,3 +514,55 @@ ChildProcess.prototype.kill = function(sig) {
// TODO: raise error if r == -1?
}
};
+
+
+// Lazy loaded.
+var isolates = null;
+
+
+function Isolate() {
+ if (!process.features.isolates) {
+ throw new Error('Compiled without isolates support.');
+ }
+
+ if (!isolates) {
+ isolates = process.binding('isolates');
+ }
+
+ this._handle = null;
+}
+inherits(Isolate, EventEmitter); // maybe inherit from ChildProcess?
+
+
+Isolate.prototype.spawn = function(options) {
+ var self = this;
+
+ if (self._handle) throw new Error('Isolate already running.');
+ self._handle = isolates.create(options.args);
+ if (!self._handle) throw new Error('Cannot create isolate.');
+
+ self._handle.onmessage = function(msg) {
+ msg = JSON.parse('' + msg);
+ self.emit('message', msg);
+ };
+
+ self._handle.onexit = function() {
+ self._handle = null;
+ self.emit('exit');
+ };
+};
+
+
+Isolate.prototype.kill = function(sig) {
+ if (!this._handle) throw new Error('Isolate not running.');
+ // ignore silently for now, need a way to signal the other thread
+};
+
+
+Isolate.prototype.send = function(msg) {
+ if (typeof msg === 'undefined') throw new TypeError('Bad argument.');
+ if (!this._handle) throw new Error('Isolate not running.');
+ msg = JSON.stringify(msg);
+ msg = new Buffer(msg);
+ return this._handle.send(msg);
+};
diff --git a/src/node.js b/src/node.js
index 1f159d6b3..1be049027 100644
--- a/src/node.js
+++ b/src/node.js
@@ -120,6 +120,21 @@
});
}
}
+
+ if (process.tid === 1) return;
+
+ // isolate initialization
+ process.send = function(msg) {
+ if (typeof msg === 'undefined') throw new TypeError('Bad argument.');
+ msg = JSON.stringify(msg);
+ msg = new Buffer(msg);
+ return process._send(msg);
+ };
+
+ process._onmessage = function(msg) {
+ msg = JSON.parse('' + msg);
+ process.emit('message', msg);
+ };
}
startup.globalVariables = function() {