@@ -65,6 +65,16 @@ class FixedCircularBuffer {
6565 this . next = null ;
6666 }
6767
68+ /**
69+ * Resets the buffer for reuse without reallocating the backing array.
70+ * Assumes all used slots have been set back to `undefined` by shift().
71+ */
72+ reset ( ) {
73+ this . bottom = 0 ;
74+ this . top = 0 ;
75+ this . next = null ;
76+ }
77+
6878 isEmpty ( ) {
6979 return this . top === this . bottom ;
7080 }
@@ -74,36 +84,48 @@ class FixedCircularBuffer {
7484 }
7585
7686 push ( data ) {
77- this . list [ this . top ] = data ;
78- this . top = ( this . top + 1 ) & kMask ;
87+ const top = this . top ;
88+ this . list [ top ] = data ;
89+ this . top = ( top + 1 ) & kMask ;
7990 }
8091
8192 shift ( ) {
82- const nextItem = this . list [ this . bottom ] ;
93+ const bottom = this . bottom ;
94+ const nextItem = this . list [ bottom ] ;
8395 if ( nextItem === undefined )
8496 return null ;
85- this . list [ this . bottom ] = undefined ;
86- this . bottom = ( this . bottom + 1 ) & kMask ;
97+ this . list [ bottom ] = undefined ;
98+ this . bottom = ( bottom + 1 ) & kMask ;
8799 return nextItem ;
88100 }
89101}
90102
91103module . exports = class FixedQueue {
92104 constructor ( ) {
93105 this . head = this . tail = new FixedCircularBuffer ( ) ;
106+ this . _spare = null ;
94107 }
95108
96109 isEmpty ( ) {
97110 return this . head . isEmpty ( ) ;
98111 }
99112
100113 push ( data ) {
101- if ( this . head . isFull ( ) ) {
102- // Head is full: Creates a new queue, sets the old queue's `.next` to it,
103- // and sets it as the new main queue.
104- this . head = this . head . next = new FixedCircularBuffer ( ) ;
114+ let head = this . head ;
115+ if ( head . isFull ( ) ) {
116+ // Head is full: reuse the spare buffer if available.
117+ // Otherwise create a new one. Link it and advance head.
118+ let nextBuf = this . _spare ;
119+ if ( nextBuf !== null ) {
120+ this . _spare = null ;
121+ nextBuf . reset ( ) ;
122+ } else {
123+ nextBuf = new FixedCircularBuffer ( ) ;
124+ }
125+ head = head . next = nextBuf ;
126+ this . head = head ;
105127 }
106- this . head . push ( data ) ;
128+ head . push ( data ) ;
107129 }
108130
109131 shift ( ) {
@@ -112,7 +134,9 @@ module.exports = class FixedQueue {
112134 if ( tail . isEmpty ( ) && tail . next !== null ) {
113135 // If there is another queue, it forms the new tail.
114136 this . tail = tail . next ;
115- tail . next = null ;
137+ // Place the emptied buffer into the spare slot for potential reuse.
138+ tail . reset ( ) ;
139+ this . _spare = tail ; // Overwrite any existing spare
116140 }
117141 return next ;
118142 }
0 commit comments