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[kOnTimeout] = unrefTimeout; } var now = Timer.now(); item._idleStart = now; var when = now + msecs; // If the actual timer is set to fire too late, or not set to fire at all, // we need to make it fire earlier if (unrefTimer.when === -1 || unrefTimer.when > when) { unrefTimer.start(msecs, 0); unrefTimer.when = when; debug('unrefTimer scheduled'); } debug('unrefList append to end'); L.append(unrefList, item); };
function _makeTimerTimeout(timer) { var domain = timer.domain; var msecs = timer._idleTimeout; L.remove(timer); // Timer has been unenrolled by another timer that fired at the same time, // so don't make it timeout. if (msecs <= 0) return; if (!timer._onTimeout) return; if (domain) { if (domain._disposed) return; domain.enter(); } debug('unreftimer firing timeout'); timer._called = true; _runOnTimeout(timer); if (domain) domain.exit(); }
function listOnTimeout() { var msecs = this.msecs; var list = this; debug('timeout callback %d', msecs); var now = Timer.now(); debug('now: %s', now); var diff, first, threw; while (first = L.peek(list)) { diff = now - first._idleStart; if (diff < msecs) { list.start(msecs - diff, 0); debug('%d list wait because diff is %d', msecs, diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the // domain or uncaughtException handler ignore the exception, // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 var domain = first.domain; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); threw = true; first._onTimeout(); if (domain) domain.exit(); threw = false; } finally { if (threw) { // We need to continue processing after domain error handling // is complete, but not by using whatever domain was left over // when the timeout threw its exception. var oldDomain = process.domain; process.domain = null; process.nextTick(function() { list[kOnTimeout](); }); process.domain = oldDomain; } } } } debug('%d list empty', msecs); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; }
function _makeTimerTimeout(timer) { var domain = timer.domain; var msecs = timer._idleTimeout; // Timer has been unenrolled by another timer that fired at the same time, // so don't make it timeout. if (!msecs || msecs < 0) return; if (!timer._onTimeout) return; if (domain && domain._disposed) return; try { var threw = true; if (domain) domain.enter(); debug('unreftimer firing timeout'); L.remove(timer); timer._onTimeout(); threw = false; if (domain) domain.exit(); } finally { if (threw) process.nextTick(unrefTimeout); } }
list.ontimeout = function() { debug('timeout callback ' + msecs); // TODO - don't stop and start the watcher all the time. // just set its repeat var now = new Date(); debug('now: ' + now); var first; while (first = L.peek(list)) { var diff = now - first._idleStart; if (diff + 1 < msecs) { list.start(diff, 0); debug(msecs + ' list wait because diff is ' + diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (first._onTimeout) first._onTimeout(); } } debug(msecs + ' list empty'); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; };
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[kOnTimeout] = unrefTimeout; } var now = Timer.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); };
function listOnTimeout() { var msecs = this.msecs; var list = this; debug('timeout callback %d', msecs); var now = Timer.now(); debug('now: %s', now); var first; while (first = L.peek(list)) { var diff = now - first._idleStart; if (diff < msecs) { list.start(msecs - diff, 0); debug('%d list wait because diff is %d', msecs, diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the // domain or uncaughtException handler ignore the exception, // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 var domain = first.domain; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; if (!first._ctx || first._ctx === first) first._onTimeout(); else first._onTimeout.call(first._ctx); if (domain) domain.exit(); threw = false; } finally { if (threw) { process.nextTick(function() { list[kOnTimeout](); }); } } } } debug('%d list empty', msecs); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; }
exports.clearImmediate = function(immediate) { if (!immediate) return; immediate._onImmediate = undefined; L.remove(immediate); if (L.isEmpty(immediateQueue)) { process._needImmediateCallback = false; } };
var unenroll = exports.unenroll = function(item) { L.remove(item); var list = lists[item._idleTimeout]; // if empty then stop the watcher debug('unenroll'); if (list && L.isEmpty(list)) { debug('unenroll: list empty'); list.stop(); } };
exports.clearImmediate = function(immediate) { if (!immediate) return; immediate._onTimeout = undefined; L.remove(immediate); if (L.isEmpty(immediateQueue)) { immediateTimer.stop(); immediateQueue.started = false; } };
var unenroll = exports.unenroll = function(item) { L.remove(item); var list = lists[item._idleTimeout]; // if empty then stop the watcher debug('unenroll'); if (list && L.isEmpty(list)) { debug('unenroll: list empty'); list.close(); delete lists[item._idleTimeout]; } // if active is called later, then we want to make sure not to insert again item._idleTimeout = -1; };
function reuse(item) { L.remove(item); var list = lists[item._idleTimeout]; // if empty - reuse the watcher if (list && L.isEmpty(list)) { debug('reuse hit'); list.stop(); delete lists[item._idleTimeout]; return list; } return null; }
function unrefTimeout() { var now = Timer.now(); debug('unrefTimer fired'); var diff, domain, first, hasQueue, threw; while (first = L.peek(unrefList)) { 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); domain = first.domain; if (!first._onTimeout) continue; if (domain && domain._disposed) continue; hasQueue = !!first._asyncQueue; try { if (hasQueue) loadAsyncQueue(first); if (domain) domain.enter(); threw = true; debug('unreftimer firing timeout'); first._onTimeout(); threw = false; if (domain) domain.exit(); if (hasQueue) unloadAsyncQueue(first); } finally { if (threw) process.nextTick(unrefTimeout); } } debug('unrefList is empty'); unrefTimer.when = -1; }
list.ontimeout = function() { debug('timeout callback ' + msecs); var now = Date.now(); debug('now: ' + (new Date(now))); var first; while (first = L.peek(list)) { var diff = now - first._idleStart; if (diff + 1 < msecs) { list.start(msecs - diff, 0); debug(msecs + ' list wait because diff is ' + diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the user's // uncaughtException handler ignores the exception, other timers that // expire on this tick should still run. If #2582 goes through, this // hack should be removed. // // https://github.com/joyent/node/issues/2631 if (first.domain) { if (first.domain._disposed) continue; first.domain.enter(); } try { first._onTimeout(); } catch (e) { if (!process.listeners('uncaughtException').length) throw e; process.emit('uncaughtException', e); } if (first.domain) first.domain.exit(); } } debug(msecs + ' list empty'); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; };
function unrefTimeout() { var now = Timer.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'); if (!first._ctx || first._ctx === first) first._onTimeout(); else first._onTimeout.call(first._ctx); threw = false; if (domain) domain.exit(); } finally { if (threw) process.nextTick(unrefTimeout); } } debug('unrefList is empty'); unrefTimer.when = -1; }
function listOnTimeout() { var msecs = this.msecs; var list = this; debug('timeout callback ' + msecs); var now = Timer.now(); var js_now = Date.now(); // now's value has been updated, consider that it doesn't need to be updated // unless a timer is added within the loop that processes the timers list // below list._addedTimer = false; debug('now: %d', now); var first; while (first = L.peek(list)) { // If the previous iteration caused a timer to be added, // update the value of "now" so that timing computations are // done correctly. See test/simple/test-timers-blocking-callback.js // for more information. if (list._addedTimer) { var js_next = Date.now(); if (js_next > js_now) { now = Timer.now(); debug('now: %d', now); } js_now = js_next; list._addedTimer = false; } var diff = now - first._monotonicStartTime; if (diff < msecs) { list.start(msecs - diff, 0); debug(msecs + ' list wait because diff is ' + diff); return; } else { L.remove(first); assert(first !== L.peek(list)); if (!first._onTimeout) continue; // v0.4 compatibility: if the timer callback throws and the // domain or uncaughtException handler ignore the exception, // other timers that expire on this tick should still run. // // https://github.com/joyent/node/issues/2631 var domain = first.domain; if (domain && domain._disposed) continue; try { if (domain) domain.enter(); var threw = true; first._onTimeout(); if (domain) domain.exit(); threw = false; } finally { if (threw) { // We need to continue processing after domain error handling // is complete, but not by using whatever domain was left over // when the timeout threw its exception. var oldDomain = process.domain; process.domain = null; process.nextTick(function() { list.ontimeout(); }); process.domain = oldDomain; } } } } debug(msecs + ' list empty'); assert(L.isEmpty(list)); list.close(); delete lists[msecs]; }
L.append(list, D); // list -> A -> B -> C -> D assert.equal(A, L.peek(list)); var x = L.shift(list); assert.equal(A, x); // list -> B -> C -> D assert.equal(B, L.peek(list)); x = L.shift(list); assert.equal(B, x); // list -> C -> D assert.equal(C, L.peek(list)); // B is already removed, so removing it again shouldn't hurt. L.remove(B); // list -> C -> D assert.equal(C, L.peek(list)); // Put B back on the list L.append(list, B); // list -> C -> D -> B assert.equal(C, L.peek(list)); L.remove(C); // list -> D -> B assert.equal(D, L.peek(list)); L.remove(B); // list -> D assert.equal(D, L.peek(list));