11'use strict' ;
22
33const TimerWrap = process . binding ( 'timer_wrap' ) . Timer ;
4- const L = require ( 'internal/linkedlist' ) ;
5- const assert = require ( 'assert' ) ;
64const util = require ( 'util' ) ;
75const debug = util . debuglog ( 'timer' ) ;
86const kOnTimeout = TimerWrap . kOnTimeout | 0 ;
@@ -131,15 +129,28 @@ function insert(item, unrefed) {
131129 lists [ msecs ] = list = createTimersList ( msecs , unrefed ) ;
132130 }
133131
134- L . append ( list , item ) ;
135- assert ( ! L . isEmpty ( list ) ) ; // list is not empty
132+ // put item at end of list
133+ if ( item . _idleNext ) {
134+ item . _idleNext . _idlePrev = item . _idlePrev ;
135+ }
136+ if ( item . _idlePrev ) {
137+ item . _idlePrev . _idleNext = item . _idleNext ;
138+ }
139+
140+ // items are linked with _idleNext -> (older) and _idlePrev -> (newer)
141+ // TODO: swap the linkage to match the intuitive older items at "prev"
142+ item . _idleNext = list . _idleNext ;
143+ item . _idlePrev = list ;
144+
145+ // the list _idleNext points to tail (newest) and _idlePrev to head (oldest)
146+ list . _idleNext . _idlePrev = item ;
147+ list . _idleNext = item ;
136148}
137149
138150function createTimersList ( msecs , unrefed ) {
139151 // Make a new linked list of timers, and create a TimerWrap to schedule
140152 // processing for the list.
141153 const list = new TimersList ( msecs , unrefed ) ;
142- L . init ( list ) ;
143154 list . _timer . _list = list ;
144155
145156 if ( unrefed === true ) list . _timer . unref ( ) ;
@@ -151,8 +162,8 @@ function createTimersList(msecs, unrefed) {
151162}
152163
153164function TimersList ( msecs , unrefed ) {
154- this . _idleNext = null ; // Create the list with the linkedlist properties to
155- this . _idlePrev = null ; // prevent any unnecessary hidden class changes.
165+ this . _idleNext = this ;
166+ this . _idlePrev = this ;
156167 this . _timer = new TimerWrap ( ) ;
157168 this . _unrefed = unrefed ;
158169 this . msecs = msecs ;
@@ -168,7 +179,8 @@ function listOnTimeout() {
168179 debug ( 'now: %d' , now ) ;
169180
170181 var diff , timer ;
171- while ( timer = L . peek ( list ) ) {
182+ while ( list . _idlePrev !== list ) {
183+ timer = list . _idlePrev ;
172184 diff = now - timer . _idleStart ;
173185
174186 // Check if this loop iteration is too early for the next timer.
@@ -185,8 +197,17 @@ function listOnTimeout() {
185197
186198 // The actual logic for when a timeout happens.
187199
188- L . remove ( timer ) ;
189- assert ( timer !== L . peek ( list ) ) ;
200+ // Remove the timer from the linked list
201+ if ( timer . _idleNext ) {
202+ timer . _idleNext . _idlePrev = timer . _idlePrev ;
203+ }
204+
205+ if ( timer . _idlePrev ) {
206+ timer . _idlePrev . _idleNext = timer . _idleNext ;
207+ }
208+
209+ timer . _idleNext = null ;
210+ timer . _idlePrev = null ;
190211
191212 if ( ! timer . _onTimeout ) continue ;
192213
@@ -210,11 +231,9 @@ function listOnTimeout() {
210231 domain . exit ( ) ;
211232 }
212233
213- // If `L.peek(list)` returned nothing, the list was either empty or we have
214- // called all of the timer timeouts.
215- // As such, we can remove the list and clean up the TimerWrap C++ handle.
234+ // All of the timer timeouts, if any, have been called.
235+ // Remove the list and clean up the TimerWrap C++ handle.
216236 debug ( '%d list empty' , msecs ) ;
217- assert ( L . isEmpty ( list ) ) ;
218237 this . close ( ) ;
219238
220239 // Either refedLists[msecs] or unrefedLists[msecs] may have been removed and
@@ -263,11 +282,21 @@ function listOnTimeoutNT(list) {
263282// Re-using an existing handle allows us to skip that, so that a second `uv_run`
264283// will return no active handles, even when running `setTimeout(fn).unref()`.
265284function reuse ( item ) {
266- L . remove ( item ) ;
285+ // Remove item from the linked list
286+ if ( item . _idleNext ) {
287+ item . _idleNext . _idlePrev = item . _idlePrev ;
288+ }
289+
290+ if ( item . _idlePrev ) {
291+ item . _idlePrev . _idleNext = item . _idleNext ;
292+ }
293+
294+ item . _idleNext = null ;
295+ item . _idlePrev = null ;
267296
268297 var list = refedLists [ item . _idleTimeout ] ;
269298 // if empty - reuse the watcher
270- if ( list && L . isEmpty ( list ) ) {
299+ if ( list && list . _idleNext === list ) {
271300 debug ( 'reuse hit' ) ;
272301 list . _timer . stop ( ) ;
273302 delete refedLists [ item . _idleTimeout ] ;
@@ -313,7 +342,8 @@ exports.enroll = function(item, msecs) {
313342 }
314343
315344 item . _idleTimeout = msecs ;
316- L . init ( item ) ;
345+ item . _idleNext = item ;
346+ item . _idlePrev = item ;
317347} ;
318348
319349
0 commit comments