Permalink
Browse files

Insert new tasks on the end.

This is a partial fix to #1245 whereby timer tasks are now invoked in the order
in which they were registered, rather than in the reverse order. However, a
better fix remains, which is to invoke tasks in the order of their start time
rather than their registration time.
  • Loading branch information...
mbostock committed May 28, 2013
1 parent eb38418 commit 2e1b96a8e21f5b9bdaa221c80066f5b9d2c79817
Showing with 55 additions and 29 deletions.
  1. +16 −11 d3.js
  2. +5 −5 d3.min.js
  3. +20 −13 src/event/timer.js
  4. +14 −0 test/event/timer-test.js
View
27 d3.js
@@ -1796,7 +1796,7 @@ d3 = function() {
}
d3.csv = d3_dsv(",", "text/csv");
d3.tsv = d3_dsv(" ", "text/tab-separated-values");
- var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queue = null, d3_timer_interval, d3_timer_timeout;
+ var d3_timer_id = 0, d3_timer_byId = {}, d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout;
d3.timer = function(callback, delay, then) {
if (arguments.length < 3) {
if (arguments.length < 2) delay = 0; else if (!isFinite(delay)) return;
@@ -1806,20 +1806,24 @@ d3 = function() {
if (timer && timer.callback === callback) {
timer.then = then;
timer.delay = delay;
- } else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
- callback: callback,
- then: then,
- delay: delay,
- next: d3_timer_queue
- };
+ } else {
+ d3_timer_byId[callback.id = ++d3_timer_id] = timer = {
+ callback: callback,
+ then: then,
+ delay: delay,
+ next: null
+ };
+ if (d3_timer_queueTail) d3_timer_queueTail.next = timer; else d3_timer_queueHead = timer;
+ d3_timer_queueTail = timer;
+ }
if (!d3_timer_interval) {
d3_timer_timeout = clearTimeout(d3_timer_timeout);
d3_timer_interval = 1;
d3_timer_frame(d3_timer_step);
}
};
function d3_timer_step() {
- var elapsed, now = Date.now(), t1 = d3_timer_queue;
+ var elapsed, now = Date.now(), t1 = d3_timer_queueHead;
while (t1) {
elapsed = now - t1.then;
if (elapsed >= t1.delay) t1.flush = t1.callback(elapsed);
@@ -1838,7 +1842,7 @@ d3 = function() {
}
}
d3.timer.flush = function() {
- var elapsed, now = Date.now(), t1 = d3_timer_queue;
+ var elapsed, now = Date.now(), t1 = d3_timer_queueHead;
while (t1) {
elapsed = now - t1.then;
if (!t1.delay) t1.flush = t1.callback(elapsed);
@@ -1847,16 +1851,17 @@ d3 = function() {
d3_timer_flush();
};
function d3_timer_flush() {
- var t0 = null, t1 = d3_timer_queue, then = Infinity;
+ var t0, t1 = d3_timer_queueHead, then = Infinity;
while (t1) {
if (t1.flush) {
delete d3_timer_byId[t1.callback.id];
- t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
+ t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
} else {
then = Math.min(then, t1.then + t1.delay);
t1 = (t0 = t1).next;
}
}
+ d3_timer_queueTail = t0;
return then;
}
var d3_timer_frame = d3_window.requestAnimationFrame || d3_window.webkitRequestAnimationFrame || d3_window.mozRequestAnimationFrame || d3_window.oRequestAnimationFrame || d3_window.msRequestAnimationFrame || function(callback) {
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -2,7 +2,8 @@ import "../core/document";
var d3_timer_id = 0,
d3_timer_byId = {},
- d3_timer_queue = null,
+ d3_timer_queueHead,
+ d3_timer_queueTail,
d3_timer_interval, // is an interval (or frame) active?
d3_timer_timeout; // is a timeout active?
@@ -21,13 +22,18 @@ d3.timer = function(callback, delay, then) {
timer.delay = delay;
}
- // Otherwise, add the callback to the queue.
- else d3_timer_byId[callback.id = ++d3_timer_id] = d3_timer_queue = {
- callback: callback,
- then: then,
- delay: delay,
- next: d3_timer_queue
- };
+ // Otherwise, add the callback to the tail of the queue.
+ else {
+ d3_timer_byId[callback.id = ++d3_timer_id] = timer = {
+ callback: callback,
+ then: then,
+ delay: delay,
+ next: null
+ };
+ if (d3_timer_queueTail) d3_timer_queueTail.next = timer;
+ else d3_timer_queueHead = timer;
+ d3_timer_queueTail = timer;
+ }
// Start animatin'!
if (!d3_timer_interval) {
@@ -40,7 +46,7 @@ d3.timer = function(callback, delay, then) {
function d3_timer_step() {
var elapsed,
now = Date.now(),
- t1 = d3_timer_queue;
+ t1 = d3_timer_queueHead;
while (t1) {
elapsed = now - t1.then;
@@ -64,7 +70,7 @@ function d3_timer_step() {
d3.timer.flush = function() {
var elapsed,
now = Date.now(),
- t1 = d3_timer_queue;
+ t1 = d3_timer_queueHead;
while (t1) {
elapsed = now - t1.then;
@@ -77,18 +83,19 @@ d3.timer.flush = function() {
// Flush after callbacks to avoid concurrent queue modification.
function d3_timer_flush() {
- var t0 = null,
- t1 = d3_timer_queue,
+ var t0,
+ t1 = d3_timer_queueHead,
then = Infinity;
while (t1) {
if (t1.flush) {
delete d3_timer_byId[t1.callback.id];
- t1 = t0 ? t0.next = t1.next : d3_timer_queue = t1.next;
+ t1 = t0 ? t0.next = t1.next : d3_timer_queueHead = t1.next;
} else {
then = Math.min(then, t1.then + t1.delay);
t1 = (t0 = t1).next;
}
}
+ d3_timer_queueTail = t0;
return then;
}
View
@@ -32,6 +32,20 @@ suite.addBatch({
"calls every 17 ms": function(info) {
assert.inDelta(info.stop - info.start, 17 * 3, 20);
}
+ },
+
+ "with multiple registered tasks": {
+ topic: function(timer) {
+ var callback = this.callback,
+ results = [];
+ timer(function() { results.push("A"); return true; });
+ timer(function() { results.push("B"); return true; });
+ timer(function() { results.push("C"); return true; });
+ timer(function() { callback(null, results); return true; })
+ },
+ "invokes tasks in the order they were registered": function(results) {
+ assert.deepEqual(results, ["A", "B", "C"]);
+ }
}
}
});

0 comments on commit 2e1b96a

Please sign in to comment.