@@ -421,90 +421,76 @@ private void Grow(int capacity)
421421 public struct Enumerator : IEnumerator < T > ,
422422 IEnumerator
423423 {
424- private readonly Queue < T > _q ;
424+ private readonly Queue < T > _queue ;
425425 private readonly int _version ;
426- private int _index ; // -1 = not started, -2 = ended/disposed
426+ private int _i ;
427427 private T ? _currentElement ;
428428
429- internal Enumerator ( Queue < T > q )
429+ internal Enumerator ( Queue < T > queue )
430430 {
431- _q = q ;
432- _version = q . _version ;
433- _index = - 1 ;
431+ _queue = queue ;
432+ _version = queue . _version ;
433+ _i = - 1 ;
434434 _currentElement = default ;
435435 }
436436
437437 public void Dispose ( )
438438 {
439- _index = - 2 ;
439+ _i = - 2 ;
440440 _currentElement = default ;
441441 }
442442
443443 public bool MoveNext ( )
444444 {
445- if ( _version != _q . _version ) ThrowHelper . ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion ( ) ;
446-
447- if ( _index == - 2 )
448- return false ;
449-
450- _index ++ ;
451-
452- if ( _index == _q . _size )
445+ if ( _version != _queue . _version )
453446 {
454- // We've run past the last element
455- _index = - 2 ;
456- _currentElement = default ;
457- return false ;
447+ ThrowHelper . ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion ( ) ;
458448 }
459449
460- // Cache some fields in locals to decrease code size
461- T [ ] array = _q . _array ;
462- uint capacity = ( uint ) array . Length ;
450+ Queue < T > q = _queue ;
451+ int size = q . _size ;
463452
464- // _index represents the 0-based index into the queue, however the queue
465- // doesn't have to start from 0 and it may not even be stored contiguously in memory.
466-
467- uint arrayIndex = ( uint ) ( _q . _head + _index ) ; // this is the actual index into the queue's backing array
468- if ( arrayIndex >= capacity )
453+ int offset = _i + 1 ;
454+ if ( ( uint ) offset < ( uint ) size )
469455 {
470- // NOTE: Originally we were using the modulo operator here, however
471- // on Intel processors it has a very high instruction latency which
472- // was slowing down the loop quite a bit.
473- // Replacing it with simple comparison/subtraction operations sped up
474- // the average foreach loop by 2x.
475-
476- arrayIndex -= capacity ; // wrap around if needed
477- }
456+ _i = offset ;
478457
479- _currentElement = array [ arrayIndex ] ;
480- return true ;
481- }
458+ T [ ] array = q . _array ;
459+ int index = q . _head + offset ;
460+ if ( ( uint ) index < ( uint ) array . Length )
461+ {
462+ _currentElement = array [ index ] ;
463+ }
464+ else
465+ {
466+ // The index has wrapped around the end of the array. Shift the index and then
467+ // get the current element. It is tempting to dedup this dereferencing with that
468+ // in the if block above, but the if block above avoids a bounds check for the
469+ // accesses that are in that portion, whereas these still incur it.
470+ index -= array . Length ;
471+ _currentElement = array [ index ] ;
472+ }
482473
483- public T Current
484- {
485- get
486- {
487- if ( _index < 0 )
488- ThrowEnumerationNotStartedOrEnded ( ) ;
489- return _currentElement ! ;
474+ return true ;
490475 }
491- }
492476
493- private void ThrowEnumerationNotStartedOrEnded ( )
494- {
495- Debug . Assert ( _index == - 1 || _index == - 2 ) ;
496- throw new InvalidOperationException ( _index == - 1 ? SR . InvalidOperation_EnumNotStarted : SR . InvalidOperation_EnumEnded ) ;
477+ _i = - 2 ;
478+ _currentElement = default ;
479+ return false ;
497480 }
498481
499- object ? IEnumerator . Current
500- {
501- get { return Current ; }
502- }
482+ public T Current => _currentElement ! ;
483+
484+ object ? IEnumerator . Current => Current ;
503485
504486 void IEnumerator . Reset ( )
505487 {
506- if ( _version != _q . _version ) ThrowHelper . ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion ( ) ;
507- _index = - 1 ;
488+ if ( _version != _queue . _version )
489+ {
490+ ThrowHelper . ThrowInvalidOperationException_InvalidOperation_EnumFailedVersion ( ) ;
491+ }
492+
493+ _i = - 1 ;
508494 _currentElement = default ;
509495 }
510496 }
0 commit comments