summaryrefslogtreecommitdiff
path: root/src/node.js
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2012-07-13 18:00:49 -0700
committerisaacs <i@izs.me>2012-07-16 21:05:10 -0700
commit4e5fe2d45aef5aacf4a6c6c2db28f0b9cc64f123 (patch)
treefbb972592182ea52107b7f1a936297768fcf298d /src/node.js
parent0109a9f90acdfdb287436676f2384f7b072fbb6a (diff)
downloadnode-4e5fe2d45aef5aacf4a6c6c2db28f0b9cc64f123.tar.gz
nextTick: Handle tick callbacks after each tick
Diffstat (limited to 'src/node.js')
-rw-r--r--src/node.js61
1 files changed, 42 insertions, 19 deletions
diff --git a/src/node.js b/src/node.js
index 029beb6c0..a86d72302 100644
--- a/src/node.js
+++ b/src/node.js
@@ -239,6 +239,8 @@
if (domain) domain.exit();
+ // process the nextTicks after each time we get called.
+ process._tickCallback();
return ret;
};
};
@@ -247,8 +249,19 @@
var nextTickQueue = [];
var nextTickIndex = 0;
var inTick = false;
+ var tickDepth = 0;
+
+ // the maximum number of times it'll process something like
+ // nextTick(function f(){nextTick(f)})
+ // It's unlikely, but not illegal, to hit this limit. When
+ // that happens, it yields to libuv's tick spinner.
+ // This is a loop counter, not a stack depth, so we aren't using
+ // up lots of memory here. I/O can sneak in before nextTick if this
+ // limit is hit, which is not ideal, but not terrible.
+ process.maxTickDepth = 1000;
function tickDone() {
+ tickDepth = 0;
nextTickQueue.splice(0, nextTickIndex);
nextTickIndex = 0;
inTick = false;
@@ -259,28 +272,38 @@
process._tickCallback = function() {
if (inTick) return;
- var nextTickLength = nextTickQueue.length;
- if (nextTickLength === 0) return;
inTick = true;
- while (nextTickIndex < nextTickLength) {
- var tock = nextTickQueue[nextTickIndex++];
- var callback = tock.callback;
- if (tock.domain) {
- if (tock.domain._disposed) continue;
- tock.domain.enter();
- }
- var threw = true;
- try {
- callback();
- threw = false;
- } finally {
- if (threw) tickDone();
- }
- if (tock.domain) {
- tock.domain.exit();
+ // always do this at least once. otherwise if process.maxTickDepth
+ // is set to some negative value, we'd never process any of them.
+ do {
+ tickDepth++;
+ var nextTickLength = nextTickQueue.length;
+ if (nextTickLength === 0) return tickDone();
+ while (nextTickIndex < nextTickLength) {
+ var tock = nextTickQueue[nextTickIndex++];
+ var callback = tock.callback;
+ if (tock.domain) {
+ if (tock.domain._disposed) continue;
+ tock.domain.enter();
+ }
+ var threw = true;
+ try {
+ callback();
+ threw = false;
+ } finally {
+ if (threw) tickDone();
+ }
+ if (tock.domain) {
+ tock.domain.exit();
+ }
}
- }
+ nextTickQueue.splice(0, nextTickIndex);
+ nextTickIndex = 0;
+
+ // continue until the max depth or we run out of tocks.
+ } while (tickDepth < process.maxTickDepth &&
+ nextTickQueue.length > 0);
tickDone();
};