From 9546a6f7434b4661704702c665284c8bb59d08f2 Mon Sep 17 00:00:00 2001 From: Tom MacWright Date: Fri, 7 Dec 2012 11:47:48 -0500 Subject: [PATCH] Limit download threads. Fixes #83 --- index.html | 1 + js/id/connection.js | 18 ++++++---- js/lib/queue.js | 84 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 6 deletions(-) create mode 100644 js/lib/queue.js diff --git a/index.html b/index.html index 640dfa51a..4cf24afff 100644 --- a/index.html +++ b/index.html @@ -23,6 +23,7 @@ + diff --git a/js/id/connection.js b/js/id/connection.js index d24aeffc1..0c10d37d3 100644 --- a/js/id/connection.js +++ b/js/id/connection.js @@ -149,10 +149,6 @@ iD.Connection = function() { return true; } - function apiRequestExtent(extent) { - bboxFromAPI(extent, event.load); - } - function loadTiles(projection) { var scaleExtent = [16, 16], s = projection.scale(), @@ -176,10 +172,20 @@ iD.Connection = function() { projection.invert([x + ts, y + ts])]; } - return tiles + var q = queue(2); + + var bboxes = tiles .filter(tileAlreadyLoaded) .map(apiExtentBox) - .map(apiRequestExtent); + .forEach(function(e) { + q.defer(bboxFromAPI, e); + }); + + q.awaitAll(function(err, res) { + var g = iD.Graph(); + res.forEach(function(r) { g = g.merge(r); }); + event.load(err, g); + }); } connection.url = function(_) { diff --git a/js/lib/queue.js b/js/lib/queue.js new file mode 100644 index 000000000..9a3b9da47 --- /dev/null +++ b/js/lib/queue.js @@ -0,0 +1,84 @@ +(function() { + if (typeof module === "undefined") self.queue = queue; + else module.exports = queue; + + queue.version = "1.0.0"; + + function queue(parallelism) { + var queue = {}, + active = 0, // number of in-flight deferrals + remaining = 0, // number of deferrals remaining + head, tail, // singly-linked list of deferrals + error = null, + results = [], + await = noop, + awaitAll; + + if (arguments.length < 1) parallelism = Infinity; + + queue.defer = function() { + if (!error) { + var node = arguments; + node.index = results.push(undefined) - 1; + if (tail) tail.next = node, tail = tail.next; + else head = tail = node; + ++remaining; + pop(); + } + return queue; + }; + + queue.await = function(f) { + await = f; + awaitAll = false; + if (!remaining) notify(); + return queue; + }; + + queue.awaitAll = function(f) { + await = f; + awaitAll = true; + if (!remaining) notify(); + return queue; + }; + + function pop() { + if (head && active < parallelism) { + var node = head, + f = node[0], + a = Array.prototype.slice.call(node, 1), + i = node.index; + if (head === tail) head = tail = null; + else head = head.next; + ++active; + a.push(function(e, r) { + --active; + if (error != null) return; + if (e != null) { + // clearing remaining cancels subsequent callbacks + // clearing head stops queued tasks from being executed + // setting error ignores subsequent calls to defer + error = e; + remaining = results = head = tail = null; + notify(); + } else { + results[i] = r; + if (--remaining) pop(); + else notify(); + } + }); + f.apply(null, a); + } + } + + function notify() { + if (error != null) await(error); + else if (awaitAll) await(null, results); + else await.apply(null, [null].concat(results)); + } + + return queue; + } + + function noop() {} +})();