@@ -118,17 +118,17 @@ public static IntervalList Merge(IntervalList x, IntervalList y)
118
118
return x ;
119
119
}
120
120
121
- public static IntervalList FromArray ( int [ ] xs )
121
+ public static IntervalList FromArray ( int [ ] xs , int length )
122
122
{
123
123
Array . Sort ( xs ) ;
124
124
125
125
IntervalList result = null ;
126
126
IntervalList current = null ;
127
127
128
128
int i = 0 ;
129
- while ( i < xs . Length ) {
129
+ while ( i < length ) {
130
130
int start = i ;
131
- while ( ( i < xs . Length - 1 ) && ( xs [ i + 1 ] == xs [ i ] + 1 ) )
131
+ while ( ( i < length - 1 ) && ( xs [ i + 1 ] == xs [ i ] + 1 ) )
132
132
i ++ ;
133
133
134
134
IntervalList interval = new IntervalList ( start , i ) ;
@@ -178,6 +178,16 @@ public int Allocate()
178
178
}
179
179
}
180
180
181
+ private void Flush ( )
182
+ {
183
+ if ( unsortedCount > 0 )
184
+ {
185
+ Base = IntervalList . Merge ( Base , IntervalList . FromArray ( unsorted , unsortedCount ) ) ;
186
+ unsortedCount = 0 ;
187
+ }
188
+ }
189
+
190
+
181
191
/**
182
192
* Make the provided integer available for allocation again. This operation
183
193
* runs in amortized O(sqrt(range size)) time: About every sqrt(range size)
@@ -189,15 +199,23 @@ public int Allocate()
189
199
*/
190
200
public void Free ( int id )
191
201
{
192
- if ( unsortedCount >= unsorted . Length ) {
193
- Base = IntervalList . Merge ( Base , IntervalList . FromArray ( unsorted ) ) ;
194
- unsortedCount = 0 ;
202
+ if ( unsortedCount >= unsorted . Length )
203
+ {
204
+ Flush ( ) ;
195
205
}
196
206
unsorted [ unsortedCount ++ ] = id ;
197
207
}
198
208
199
209
public bool Reserve ( int id )
200
210
{
211
+ // We always flush before reserving because the only way to determine
212
+ // if an ID is in the unsorted array is through a linear scan. This leads
213
+ // us to the potentially expensive situation where there is a large unsorted
214
+ // array and we reserve several IDs, incurring the cost of the scan each time.
215
+ // Flushing makes sure the array is always empty and does no additional work if
216
+ // reserve is called twice.
217
+ Flush ( ) ;
218
+
201
219
IntervalList current = Base ;
202
220
203
221
while ( current != null )
0 commit comments