in rd-net/Lifetimes/Serialization/NativeMemoryPool.cs [88:168]
internal static Cookie ReserveMiss()
{
// try to search in the array of all memory blocks
ThreadMemoryHolder? h;
if (SearchAndReserve(out h))
return new Cookie(h);
if (AllocateNew(out h))
return new Cookie(h, causedAllocation: true);
// All items in array blocks are busy and not available, increase the array size and try once more
lock (ourLock)
{
var newBlocks = new ThreadMemoryHolder[ourBlocks.Length * 2];
Array.Copy(ourBlocks, newBlocks, ourBlocks.Length);
ourBlocks = newBlocks;
if (SearchAndReserve(out h))
return new Cookie(h);
if (AllocateNew(out h))
return new Cookie(h, causedAllocation: true);
}
Assertion.Fail("Unable to reserve a native memory block");
return new Cookie();
bool SearchAndReserve([MaybeNullWhen(false)] out ThreadMemoryHolder holder)
{
var blocks = ourBlocks;
var start = Thread.CurrentThread.ManagedThreadId % blocks.Length;
for (int i = start; i < blocks.Length; i++)
{
var candidate = blocks[i];
if (candidate == null)
break;
if (candidate.TryReserve())
{
ourThreadMemory = holder = candidate;
return true;
}
}
for (int i = 0; i < start; i++)
{
var candidate = blocks[i];
if (candidate == null)
break;
if (candidate.TryReserve())
{
ourThreadMemory = holder = candidate;
return true;
}
}
holder = null;
return false;
}
bool AllocateNew([MaybeNullWhen(false)] out ThreadMemoryHolder holder)
{
lock (ourLock)
{
for (int i = 0; i < ourBlocks.Length; i++)
{
if (ourBlocks[i] != null)
continue;
ourThreadMemory = holder = new ThreadMemoryHolder();
if (holder.TryReserve())
{
ourBlocks[i] = holder;
return true;
}
Assertion.Fail("Unable to reserve newly created memory block");
}
}
holder = null;
return false;
}
}