@@ -30,6 +30,17 @@ var TIMEOUT_MAX = 2147483647; // 2^31-1
3030
3131var debug = require ( 'util' ) . debuglog ( 'timer' ) ;
3232
33+ var asyncFlags = process . _asyncFlags ;
34+ var runAsyncQueue = process . _runAsyncQueue ;
35+ var loadAsyncQueue = process . _loadAsyncQueue ;
36+ var unloadAsyncQueue = process . _unloadAsyncQueue ;
37+
38+ // Do a little housekeeping.
39+ delete process . _asyncFlags ;
40+ delete process . _runAsyncQueue ;
41+ delete process . _loadAsyncQueue ;
42+ delete process . _unloadAsyncQueue ;
43+
3344
3445// IDLE TIMEOUTS
3546//
@@ -44,6 +55,9 @@ var debug = require('util').debuglog('timer');
4455// value = list
4556var lists = { } ;
4657
58+ // Make Timer as monomorphic as possible.
59+ Timer . prototype . _asyncQueue = undefined ;
60+
4761// the main function - creates lists on demand and the watchers associated
4862// with them.
4963function insert ( item , msecs ) {
@@ -80,9 +94,9 @@ function listOnTimeout() {
8094 var now = Timer . now ( ) ;
8195 debug ( 'now: %s' , now ) ;
8296
83- var first ;
97+ var diff , first , hasQueue , threw ;
8498 while ( first = L . peek ( list ) ) {
85- var diff = now - first . _idleStart ;
99+ diff = now - first . _idleStart ;
86100 if ( diff < msecs ) {
87101 list . start ( msecs - diff , 0 ) ;
88102 debug ( '%d list wait because diff is %d' , msecs , diff ) ;
@@ -99,12 +113,20 @@ function listOnTimeout() {
99113 //
100114 // https://github.com/joyent/node/issues/2631
101115 var domain = first . domain ;
102- if ( domain && domain . _disposed ) continue ;
116+ if ( domain && domain . _disposed )
117+ continue ;
118+
119+ hasQueue = ! ! first . _asyncQueue ;
120+
103121 try {
122+ if ( hasQueue )
123+ loadAsyncQueue ( first ) ;
104124 if ( domain )
105125 domain . enter ( ) ;
106- var threw = true ;
126+ threw = true ;
107127 first . _onTimeout ( ) ;
128+ if ( hasQueue )
129+ unloadAsyncQueue ( first ) ;
108130 if ( domain )
109131 domain . exit ( ) ;
110132 threw = false ;
@@ -162,7 +184,6 @@ exports.enroll = function(item, msecs) {
162184exports . active = function ( item ) {
163185 var msecs = item . _idleTimeout ;
164186 if ( msecs >= 0 ) {
165-
166187 var list = lists [ msecs ] ;
167188 if ( ! list || L . isEmpty ( list ) ) {
168189 insert ( item , msecs ) ;
@@ -171,6 +192,11 @@ exports.active = function(item) {
171192 L . append ( list , item ) ;
172193 }
173194 }
195+ // Whether or not a new TimerWrap needed to be created, this should run
196+ // for each item. This way each "item" (i.e. timer) can properly have
197+ // their own domain assigned.
198+ if ( asyncFlags [ 0 ] > 0 )
199+ runAsyncQueue ( item ) ;
174200} ;
175201
176202
@@ -316,16 +342,43 @@ L.init(immediateQueue);
316342
317343function processImmediate ( ) {
318344 var queue = immediateQueue ;
345+ var domain , hasQueue , immediate ;
319346
320347 immediateQueue = { } ;
321348 L . init ( immediateQueue ) ;
322349
323350 while ( L . isEmpty ( queue ) === false ) {
324- var immediate = L . shift ( queue ) ;
325- var domain = immediate . domain ;
326- if ( domain ) domain . enter ( ) ;
327- immediate . _onImmediate ( ) ;
328- if ( domain ) domain . exit ( ) ;
351+ immediate = L . shift ( queue ) ;
352+ hasQueue = ! ! immediate . _asyncQueue ;
353+ domain = immediate . domain ;
354+
355+ if ( hasQueue )
356+ loadAsyncQueue ( immediate ) ;
357+ if ( domain )
358+ domain . enter ( ) ;
359+
360+ var threw = true ;
361+ try {
362+ immediate . _onImmediate ( ) ;
363+ threw = false ;
364+ } finally {
365+ if ( threw ) {
366+ if ( ! L . isEmpty ( queue ) ) {
367+ // Handle any remaining on next tick, assuming we're still
368+ // alive to do so.
369+ while ( ! L . isEmpty ( immediateQueue ) ) {
370+ L . append ( queue , L . shift ( immediateQueue ) ) ;
371+ }
372+ immediateQueue = queue ;
373+ process . nextTick ( processImmediate ) ;
374+ }
375+ }
376+ }
377+
378+ if ( hasQueue )
379+ unloadAsyncQueue ( immediate ) ;
380+ if ( domain )
381+ domain . exit ( ) ;
329382 }
330383
331384 // Only round-trip to C++ land if we have to. Calling clearImmediate() on an
@@ -357,7 +410,11 @@ exports.setImmediate = function(callback) {
357410 process . _immediateCallback = processImmediate ;
358411 }
359412
360- if ( process . domain ) immediate . domain = process . domain ;
413+ // setImmediates are handled more like nextTicks.
414+ if ( asyncFlags [ 0 ] > 0 )
415+ runAsyncQueue ( immediate ) ;
416+ if ( process . domain )
417+ immediate . domain = process . domain ;
361418
362419 L . append ( immediateQueue , immediate ) ;
363420
@@ -389,9 +446,10 @@ function unrefTimeout() {
389446
390447 debug ( 'unrefTimer fired' ) ;
391448
392- var first ;
449+ var diff , domain , first , hasQueue , threw ;
393450 while ( first = L . peek ( unrefList ) ) {
394- var diff = now - first . _idleStart ;
451+ diff = now - first . _idleStart ;
452+ hasQueue = ! ! first . _asyncQueue ;
395453
396454 if ( diff < first . _idleTimeout ) {
397455 diff = first . _idleTimeout - diff ;
@@ -403,17 +461,21 @@ function unrefTimeout() {
403461
404462 L . remove ( first ) ;
405463
406- var domain = first . domain ;
464+ domain = first . domain ;
407465
408466 if ( ! first . _onTimeout ) continue ;
409467 if ( domain && domain . _disposed ) continue ;
410468
411469 try {
470+ if ( hasQueue )
471+ loadAsyncQueue ( first ) ;
412472 if ( domain ) domain . enter ( ) ;
413- var threw = true ;
473+ threw = true ;
414474 debug ( 'unreftimer firing timeout' ) ;
415475 first . _onTimeout ( ) ;
416476 threw = false ;
477+ if ( hasQueue )
478+ unloadAsyncQueue ( first ) ;
417479 if ( domain ) domain . exit ( ) ;
418480 } finally {
419481 if ( threw ) process . nextTick ( unrefTimeout ) ;
0 commit comments