diff --git a/debug/shared_workers.html b/debug/shared_workers.html
new file mode 100644
index 00000000000..e36330e7fa7
--- /dev/null
+++ b/debug/shared_workers.html
@@ -0,0 +1,122 @@
+
+
+
+ Mapbox GL JS debug page
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Waiting for data...
+
+
+
+
+
+
+
+
+
diff --git a/js/util/dispatcher.js b/js/util/dispatcher.js
index cc7a9206e9b..51e9fa3b41f 100644
--- a/js/util/dispatcher.js
+++ b/js/util/dispatcher.js
@@ -1,10 +1,11 @@
'use strict';
+var WorkerPool = require('./worker_pool');
var util = require('./util');
var Actor = require('./actor');
-var WebWorker = require('./web_worker');
module.exports = Dispatcher;
+Dispatcher.workerPool = new WorkerPool();
/**
* Responsible for sending messages from a {@link Source} to an associated
@@ -17,8 +18,9 @@ function Dispatcher(length, parent) {
this.actors = [];
this.currentActor = 0;
this.id = util.uniqueId();
+ var workers = Dispatcher.workerPool.acquire(this.id, length);
for (var i = 0; i < length; i++) {
- var worker = new WebWorker();
+ var worker = workers[i];
var actor = new Actor(worker, parent, this.id);
actor.name = "Worker " + i;
this.actors.push(actor);
@@ -66,9 +68,8 @@ Dispatcher.prototype = {
},
remove: function() {
- for (var i = 0; i < this.actors.length; i++) {
- this.actors[i].target.terminate();
- }
+ Dispatcher.workerPool.release(this.id);
this.actors = [];
}
};
+
diff --git a/js/util/worker_pool.js b/js/util/worker_pool.js
new file mode 100644
index 00000000000..246cf80b1b7
--- /dev/null
+++ b/js/util/worker_pool.js
@@ -0,0 +1,35 @@
+'use strict';
+
+var assert = require('assert');
+var WebWorker = require('./web_worker');
+
+module.exports = WorkerPool;
+
+function WorkerPool() {
+ this.workers = [];
+ this.active = {};
+}
+
+WorkerPool.prototype = {
+ acquire: function (mapId, workerCount) {
+ this._resize(workerCount);
+ this.active[mapId] = workerCount;
+ return this.workers.slice(0, workerCount);
+ },
+
+ release: function (mapId) {
+ delete this.active[mapId];
+ if (Object.keys(this.active).length === 0) {
+ this.workers.forEach(function (w) { w.terminate(); });
+ this.workers = [];
+ }
+ },
+
+ _resize: function (len) {
+ assert(typeof len === 'number');
+ while (this.workers.length < len) {
+ this.workers.push(new WebWorker());
+ }
+ }
+};
+
diff --git a/test/js/source/worker.test.js b/test/js/source/worker.test.js
index dcea5af78f6..2f9919553fd 100644
--- a/test/js/source/worker.test.js
+++ b/test/js/source/worker.test.js
@@ -26,7 +26,7 @@ test('before', function(t) {
test('load tile', function(t) {
t.test('calls callback on error', function(t) {
var worker = new Worker(_self);
- worker['load tile']({
+ worker['load tile'](0, {
source: 'source',
uid: 0,
url: 'http://localhost:2900/error'
@@ -42,25 +42,25 @@ test('load tile', function(t) {
test('set layers', function(t) {
var worker = new Worker(_self);
- worker['set layers']([
+ worker['set layers'](0, [
{ id: 'one', type: 'circle', paint: { 'circle-color': 'red' } },
{ id: 'two', type: 'circle', paint: { 'circle-color': 'green' } },
{ id: 'three', ref: 'two', type: 'circle', paint: { 'circle-color': 'blue' } }
]);
- t.equal(worker.layers.one.id, 'one');
- t.equal(worker.layers.two.id, 'two');
- t.equal(worker.layers.three.id, 'three');
+ t.equal(worker.layers[0].one.id, 'one');
+ t.equal(worker.layers[0].two.id, 'two');
+ t.equal(worker.layers[0].three.id, 'three');
- t.equal(worker.layers.one.getPaintProperty('circle-color'), 'red');
- t.equal(worker.layers.two.getPaintProperty('circle-color'), 'green');
- t.equal(worker.layers.three.getPaintProperty('circle-color'), 'blue');
+ t.equal(worker.layers[0].one.getPaintProperty('circle-color'), 'red');
+ t.equal(worker.layers[0].two.getPaintProperty('circle-color'), 'green');
+ t.equal(worker.layers[0].three.getPaintProperty('circle-color'), 'blue');
- t.equal(worker.layerFamilies.one.length, 1);
- t.equal(worker.layerFamilies.one[0].id, 'one');
- t.equal(worker.layerFamilies.two.length, 2);
- t.equal(worker.layerFamilies.two[0].id, 'two');
- t.equal(worker.layerFamilies.two[1].id, 'three');
+ t.equal(worker.layerFamilies[0].one.length, 1);
+ t.equal(worker.layerFamilies[0].one[0].id, 'one');
+ t.equal(worker.layerFamilies[0].two.length, 2);
+ t.equal(worker.layerFamilies[0].two[0].id, 'two');
+ t.equal(worker.layerFamilies[0].two[1].id, 'three');
t.end();
});
@@ -68,25 +68,65 @@ test('set layers', function(t) {
test('update layers', function(t) {
var worker = new Worker(_self);
- worker['set layers']([
+ worker['set layers'](0, [
{ id: 'one', type: 'circle', paint: { 'circle-color': 'red' } },
{ id: 'two', type: 'circle', paint: { 'circle-color': 'green' } },
{ id: 'three', ref: 'two', type: 'circle', paint: { 'circle-color': 'blue' } }
]);
- worker['update layers']({
+ worker['update layers'](0, {
one: { id: 'one', type: 'circle', paint: { 'circle-color': 'cyan' } },
two: { id: 'two', type: 'circle', paint: { 'circle-color': 'magenta' } },
three: { id: 'three', ref: 'two', type: 'circle', paint: { 'circle-color': 'yellow' } }
});
- t.equal(worker.layers.one.getPaintProperty('circle-color'), 'cyan');
- t.equal(worker.layers.two.getPaintProperty('circle-color'), 'magenta');
- t.equal(worker.layers.three.getPaintProperty('circle-color'), 'yellow');
+ t.equal(worker.layers[0].one.getPaintProperty('circle-color'), 'cyan');
+ t.equal(worker.layers[0].two.getPaintProperty('circle-color'), 'magenta');
+ t.equal(worker.layers[0].three.getPaintProperty('circle-color'), 'yellow');
t.end();
});
+test('update layers isolates different instances\' data', function(t) {
+ var worker = new Worker(_self);
+
+ worker['set layers'](0, [
+ { id: 'one', type: 'circle', paint: { 'circle-color': 'red' } },
+ { id: 'two', type: 'circle', paint: { 'circle-color': 'green' } },
+ { id: 'three', ref: 'two', type: 'circle', paint: { 'circle-color': 'blue' } }
+ ]);
+
+ worker['set layers'](1, [
+ { id: 'one', type: 'circle', paint: { 'circle-color': 'red' } },
+ { id: 'two', type: 'circle', paint: { 'circle-color': 'green' } },
+ { id: 'three', ref: 'two', type: 'circle', paint: { 'circle-color': 'blue' } }
+ ]);
+
+ worker['update layers'](1, {
+ one: { id: 'one', type: 'circle', paint: { 'circle-color': 'cyan' } },
+ two: { id: 'two', type: 'circle', paint: { 'circle-color': 'magenta' } },
+ three: { id: 'three', ref: 'two', type: 'circle', paint: { 'circle-color': 'yellow' } }
+ });
+
+ t.equal(worker.layers[0].one.id, 'one');
+ t.equal(worker.layers[0].two.id, 'two');
+ t.equal(worker.layers[0].three.id, 'three');
+
+ t.equal(worker.layers[0].one.getPaintProperty('circle-color'), 'red');
+ t.equal(worker.layers[0].two.getPaintProperty('circle-color'), 'green');
+ t.equal(worker.layers[0].three.getPaintProperty('circle-color'), 'blue');
+
+ t.equal(worker.layerFamilies[0].one.length, 1);
+ t.equal(worker.layerFamilies[0].one[0].id, 'one');
+ t.equal(worker.layerFamilies[0].two.length, 2);
+ t.equal(worker.layerFamilies[0].two[0].id, 'two');
+ t.equal(worker.layerFamilies[0].two[1].id, 'three');
+
+
+ t.end();
+});
+
+
test('after', function(t) {
server.close(t.end);
});