From 4e5fe2d45aef5aacf4a6c6c2db28f0b9cc64f123 Mon Sep 17 00:00:00 2001 From: isaacs Date: Fri, 13 Jul 2012 18:00:49 -0700 Subject: nextTick: Handle tick callbacks after each tick --- src/node.js | 61 ++++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 19 deletions(-) (limited to 'src/node.js') 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(); }; -- cgit v1.2.1