@@ -15,7 +15,7 @@ namespace DotNext.Collections.Concurrent;
15
15
/// </remarks>
16
16
[ EditorBrowsable ( EditorBrowsableState . Advanced ) ]
17
17
[ StructLayout ( LayoutKind . Auto ) ]
18
- public struct IndexPool : ISupplier < int > , IConsumer < int > , IReadOnlyCollection < int >
18
+ public struct IndexPool : ISupplier < int > , IConsumer < int > , IReadOnlyCollection < int > , IResettable
19
19
{
20
20
private readonly int maxValue ;
21
21
private ulong bitmask ;
@@ -46,6 +46,21 @@ public IndexPool(int maxValue)
46
46
this . maxValue = maxValue ;
47
47
}
48
48
49
+ /// <summary>
50
+ /// Initializes a new pool that can return an integer within the range [0..<paramref name="maxValue"/>].
51
+ /// </summary>
52
+ /// <param name="maxValue">The maximum possible value to return, inclusive.</param>
53
+ /// <param name="isEmpty"><see langword="true"/> to initialize a pool with an empty set of integers; otherwise, <see langword="false"/>.</param>
54
+ /// <exception cref="ArgumentOutOfRangeException"></exception>
55
+ public IndexPool ( int maxValue , bool isEmpty )
56
+ {
57
+ if ( ( uint ) maxValue > ( uint ) MaxValue )
58
+ throw new ArgumentOutOfRangeException ( nameof ( maxValue ) ) ;
59
+
60
+ this . maxValue = maxValue ;
61
+ bitmask = isEmpty ? 0UL : ulong . MaxValue ;
62
+ }
63
+
49
64
/// <summary>
50
65
/// Gets the maximum number that can be returned by the pool.
51
66
/// </summary>
@@ -109,28 +124,28 @@ public int Take()
109
124
}
110
125
111
126
/// <summary>
112
- /// Takes all available indicies , atomically.
127
+ /// Takes all available indices , atomically.
113
128
/// </summary>
114
- /// <param name="indicies ">
115
- /// The buffer to be modified with the indicies taken from the pool.
129
+ /// <param name="indices ">
130
+ /// The buffer to be modified with the indices taken from the pool.
116
131
/// The size of the buffer should not be less than <see cref="Capacity"/>.
117
132
/// </param>
118
- /// <returns>The number of indicies written to the buffer.</returns>
119
- /// <exception cref="ArgumentOutOfRangeException"><paramref name="indicies "/> is too small to place indicies .</exception>
133
+ /// <returns>The number of indices written to the buffer.</returns>
134
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="indices "/> is too small to place indices .</exception>
120
135
/// <seealso cref="Return(ReadOnlySpan{int})"/>
121
- public int Take ( Span < int > indicies )
136
+ public int Take ( Span < int > indices )
122
137
{
123
- if ( indicies . Length < Capacity )
124
- throw new ArgumentOutOfRangeException ( nameof ( indicies ) ) ;
138
+ if ( indices . Length < Capacity )
139
+ throw new ArgumentOutOfRangeException ( nameof ( indices ) ) ;
125
140
126
141
var oldValue = Interlocked . Exchange ( ref bitmask , 0UL ) ;
127
142
var bufferOffset = 0 ;
128
143
129
- for ( int bitPosition = 0 ; bitPosition < Capacity ; bitPosition ++ )
144
+ for ( var bitPosition = 0 ; bitPosition < Capacity ; bitPosition ++ )
130
145
{
131
146
if ( Contains ( oldValue , bitPosition ) )
132
147
{
133
- indicies [ bufferOffset ++ ] = bitPosition ;
148
+ indices [ bufferOffset ++ ] = bitPosition ;
134
149
}
135
150
}
136
151
@@ -160,21 +175,26 @@ static void ThrowArgumentOutOfRangeException()
160
175
}
161
176
162
177
/// <summary>
163
- /// Returns multiple indicies , atomically.
178
+ /// Returns multiple indices , atomically.
164
179
/// </summary>
165
- /// <param name="indicies ">The buffer of indicies to return back to the pool.</param>
166
- public void Return ( ReadOnlySpan < int > indicies )
180
+ /// <param name="indices ">The buffer of indices to return back to the pool.</param>
181
+ public void Return ( ReadOnlySpan < int > indices )
167
182
{
168
183
var newValue = 0UL ;
169
184
170
- foreach ( var index in indicies )
185
+ foreach ( var index in indices )
171
186
{
172
187
newValue |= 1UL << index ;
173
188
}
174
189
175
190
Interlocked . Or ( ref bitmask , newValue ) ;
176
191
}
177
192
193
+ /// <summary>
194
+ /// Returns all values to the pool.
195
+ /// </summary>
196
+ public void Reset ( ) => Volatile . Write ( ref bitmask , ulong . MaxValue ) ;
197
+
178
198
/// <inheritdoc/>
179
199
void IConsumer < int > . Invoke ( int value ) => Return ( value ) ;
180
200
@@ -190,14 +210,14 @@ private static bool Contains(ulong bitmask, int index)
190
210
=> ( bitmask & ( 1UL << index ) ) is not 0UL ;
191
211
192
212
/// <summary>
193
- /// Gets the number of available indicies .
213
+ /// Gets the number of available indices .
194
214
/// </summary>
195
215
public readonly int Count => Math . Min ( BitOperations . PopCount ( bitmask ) , maxValue + 1 ) ;
196
216
197
217
/// <summary>
198
- /// Gets an enumerator over available indicies in the pool.
218
+ /// Gets an enumerator over available indices in the pool.
199
219
/// </summary>
200
- /// <returns>The enumerator over available indicies in this pool.</returns>
220
+ /// <returns>The enumerator over available indices in this pool.</returns>
201
221
public readonly Enumerator GetEnumerator ( ) => new ( Volatile . Read ( in bitmask ) , maxValue ) ;
202
222
203
223
/// <inheritdoc/>
@@ -207,7 +227,7 @@ private static bool Contains(ulong bitmask, int index)
207
227
readonly IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) . AsClassicEnumerator ( ) ;
208
228
209
229
/// <summary>
210
- /// Represents an enumerator over available indicies in the pool.
230
+ /// Represents an enumerator over available indices in the pool.
211
231
/// </summary>
212
232
[ StructLayout ( LayoutKind . Auto ) ]
213
233
public struct Enumerator
0 commit comments