summaryrefslogtreecommitdiff
path: root/lib/timers.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/timers.js')
-rw-r--r--lib/timers.js108
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/timers.js b/lib/timers.js
index 1412928c51..8911e2ebf7 100644
--- a/lib/timers.js
+++ b/lib/timers.js
@@ -368,3 +368,111 @@ exports.clearImmediate = function(immediate) {
process._needImmediateCallback = false;
}
};
+
+
+// Internal APIs that need timeouts should use timers._unrefActive isntead of
+// timers.active as internal timeouts shouldn't hold the loop open
+
+var unrefList, unrefTimer;
+
+
+function unrefTimeout() {
+ var now = Date.now();
+
+ debug('unrefTimer fired');
+
+ var first;
+ while (first = L.peek(unrefList)) {
+ var diff = now - first._idleStart;
+
+ if (diff < first._idleTimeout) {
+ diff = first._idleTimeout - diff;
+ unrefTimer.start(diff, 0);
+ unrefTimer.when = now + diff;
+ debug('unrefTimer rescheudling for later');
+ return;
+ }
+
+ L.remove(first);
+
+ var domain = first.domain;
+
+ if (!first._onTimeout) continue;
+ if (domain && domain._disposed) continue;
+
+ try {
+ if (domain) domain.enter();
+ var threw = true;
+ debug('unreftimer firing timeout');
+ first._onTimeout();
+ threw = false;
+ if (domain) domain.exit();
+ } finally {
+ if (threw) process.nextTick(unrefTimeout);
+ }
+ }
+
+ debug('unrefList is empty');
+ unrefTimer.when = -1;
+}
+
+
+exports._unrefActive = function(item) {
+ var msecs = item._idleTimeout;
+ if (!msecs || msecs < 0) return;
+ assert(msecs >= 0);
+
+ L.remove(item);
+
+ if (!unrefList) {
+ debug('unrefList initialized');
+ unrefList = {};
+ L.init(unrefList);
+
+ debug('unrefTimer initialized');
+ unrefTimer = new Timer();
+ unrefTimer.unref();
+ unrefTimer.when = -1;
+ unrefTimer.ontimeout = unrefTimeout;
+ }
+
+ var now = Date.now();
+ item._idleStart = now;
+
+ if (L.isEmpty(unrefList)) {
+ debug('unrefList empty');
+ L.append(unrefList, item);
+
+ unrefTimer.start(msecs, 0);
+ unrefTimer.when = now + msecs;
+ debug('unrefTimer scheduled');
+ return;
+ }
+
+ var when = now + msecs;
+
+ debug('unrefList find where we can insert');
+
+ var cur, them;
+
+ for (cur = unrefList._idlePrev; cur != unrefList; cur = cur._idlePrev) {
+ them = cur._idleStart + cur._idleTimeout;
+
+ if (when < them) {
+ debug('unrefList inserting into middle of list');
+
+ L.append(cur, item);
+
+ if (unrefTimer.when > when) {
+ debug('unrefTimer is scheduled to fire too late, reschedule');
+ unrefTimer.start(msecs, 0);
+ unrefTimer.when = when;
+ }
+
+ return;
+ }
+ }
+
+ debug('unrefList append to end');
+ L.append(unrefList, item);
+};