Skip to content

Commit

Permalink
Insert new tasks on the end.
Browse files Browse the repository at this point in the history
This is a partial fix to d3#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 2e1b96a
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 29 deletions.
27 changes: 16 additions & 11 deletions d3.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -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) {
Expand Down
10 changes: 5 additions & 5 deletions d3.min.js

Large diffs are not rendered by default.

33 changes: 20 additions & 13 deletions src/event/timer.js
Original file line number Diff line number Diff line change
Expand Up @@ -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?

Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
}

Expand Down
14 changes: 14 additions & 0 deletions test/event/timer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"]);
}
}
}
});
Expand Down

0 comments on commit 2e1b96a

Please sign in to comment.