internal static Cookie ReserveMiss()

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;
      }
    }