forked from webpack/webpack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWorkers.js
More file actions
105 lines (97 loc) · 2.58 KB
/
Workers.js
File metadata and controls
105 lines (97 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var child_process = require("child_process");
function disconnectWorker(worker) {
if(worker.disconnect)
worker.disconnect();
else if(worker.kill)
worker.kill();
else
worker.process.kill();
}
function Workers(moduleToFork, count) {
this.nextId = 1;
this.workers = [];
this.workersRegister = [];
this.forkedWorkers = [];
this.workersJobs = [];
this.callbacks = {};
for(var i = 0; i < count; i++) {
var worker = child_process.fork(moduleToFork);
this.bindWorker(worker, i);
}
}
module.exports = Workers;
Workers.prototype.run = function() {
var args = Array.prototype.slice.call(arguments, 0);
var worker = -1;
var minJobs = -1;
this.workersJobs.forEach(function(jobs, idx) {
if(jobs < minJobs || minJobs == -1) {
minJobs = jobs;
worker = idx;
}
});
if(worker < 0) throw new Error("Not ready! Check workers.ready().");
args.unshift(worker);
this.pushJob.apply(this, args);
}
Workers.prototype.bindWorker = function(worker, idx) {
worker.send(null);
worker.once("message", function(msg) {
if(msg == "ready") {
idx = this.workers.length;
this.workers.push(worker);
this.workersJobs.push(0);
this.workersRegister.push({});
worker.on("message", function(result) {
this.workersJobs[idx]--;
var id = result.shift();
var callback = this.callbacks[id];
delete this.callbacks[id];
callback.apply(null, result);
}.bind(this));
} else {
disconnectWorker(worker);
this.forkedWorkers.splice(idx, 1);
}
}.bind(this));
}
Workers.prototype.ready = function() {
return this.workers.length > 0;
}
Workers.prototype.pushJob = function(worker) {
var args = Array.prototype.slice.call(arguments, 0);
var callback = args.pop();
var id = this.nextId++;
this.callbacks[id] = callback;
args[0] = id;
this.workersJobs[worker]++;
for(var i = 2; i < args.length; i++)
args[i] = JSON.stringify(args[i]);
var reg = this.workersRegister[worker][args[1]];
var regMapping = null;
var newValues = args.slice(2);
this.workersRegister[worker][args[1]] = newValues;
if(reg && newValues.length == reg.length) {
regMapping = [];
for(var i = 0; i < reg.length; i++) {
var match = reg[i] == newValues[i];
regMapping.push(match);
if(match) args[i+2] = null;
}
}
args.splice(2, 0, regMapping);
this.workers[worker].send(args);
}
Workers.prototype.close = function() {
this.workers.forEach(disconnectWorker);
this.workers.length = 0;
this.workersJobs.length = 0;
this.workersRegister.length = 0;
}
Workers.prototype.toJSON = function() {
return {};
}