@@ -35,7 +35,7 @@ heap allocation.
3535/// </summary>
3636public sealed class UnmanagedStringPool : IDisposable
3737{
38- public const int EmptyStringAllocationId = 0 ; // Reserved for empty strings
38+ public const uint EmptyStringAllocationId = 0 ; // Reserved for empty strings
3939 private const int DefaultCollectionSize = 16 ; // Default size for internal collections
4040 private const double FragmentationThreshold = 35.0 ; // Fragmentation threshold for triggering coalescing (percentage)
4141 private const int MinimumBlocksForCoalescing = 8 ; // Minimum number of free blocks before considering coalescing
@@ -45,7 +45,7 @@ public sealed class UnmanagedStringPool : IDisposable
4545 private IntPtr basePtr ; // Base pointer to the unmanaged memory block
4646 private int capacityBytes ; // Total capacity in bytes of the pool
4747 private int offsetFromBase ; // Current offset from the base pointer, tracks how much space has been used
48- private int lastAllocationId ; // Last allocation ID used, starts at 0. Monotonically increasing
48+ private uint lastAllocationId ; // Last allocation ID used, starts at 0. Monotonically increasing
4949 private int freeOperationsSinceLastCoalesce ; // Track recent coalescing to avoid excessive operations
5050 private int totalFreeBlocks ; // Total number of free blocks in the pool
5151 private int totalFreeBytes ; // Running total of free bytes to avoid recalculation
@@ -54,7 +54,7 @@ public sealed class UnmanagedStringPool : IDisposable
5454 private readonly SortedList < int , List < FreeBlock > > freeBlocksBySize = new ( DefaultCollectionSize ) ;
5555
5656 // Central registry of allocated , keyed by allocation ID
57- private readonly Dictionary < int , AllocationInfo > allocations = new ( DefaultCollectionSize ) ;
57+ private readonly Dictionary < uint , AllocationInfo > allocations = new ( DefaultCollectionSize ) ;
5858
5959 /// <summary>
6060 /// Information about an allocated string. OffsetBytes is a convenience field, for when the block is freed. 16 bytes total
@@ -322,7 +322,7 @@ internal PooledString Allocate(int lengthChars)
322322 /// Get allocation info for a valid allocation ID
323323 /// </summary>
324324 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
325- internal AllocationInfo GetAllocationInfo ( int id )
325+ internal AllocationInfo GetAllocationInfo ( uint id )
326326 {
327327 if ( id == EmptyStringAllocationId ) {
328328 return new ( IntPtr . Zero , 0 , 0 ) ;
@@ -336,7 +336,7 @@ internal AllocationInfo GetAllocationInfo(int id)
336336 /// <summary>
337337 /// Mark a string's memory as free for reuse
338338 /// </summary>
339- internal void FreeString ( int id )
339+ internal void FreeString ( uint id )
340340 {
341341 if ( IsDisposed || id == EmptyStringAllocationId ) {
342342 // Empty strings do not need to be freed, they are always available
@@ -387,8 +387,9 @@ private static int AlignSize(int sizeBytes)
387387 [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
388388 private PooledString RegisterAllocation ( IntPtr ptr , int lengthChars , int offset )
389389 {
390- if ( lastAllocationId == int . MaxValue ) {
391- // in the unlikely event we reach MaxValue (2 billion+ allocations) we cannot allocate more
390+ if ( lastAllocationId == uint . MaxValue ) {
391+ // in the unlikely event we reach MaxValue (4 billion+ allocations) we cannot allocate more
392+ // it is more likely if the pool is long-lived and cleared repeatedly
392393 throw new OutOfMemoryException ( "Allocation overflow" ) ;
393394 }
394395
0 commit comments