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(out ThreadMemoryHolder holder) { var blocks = ourBlocks; var start = Thread.CurrentThread.ManagedThreadId % blocks.Length; for (int i = start; i < blocks.Length; i++) { holder = blocks[i]; if (holder == null) { break; } if (holder.TryReserve()) { ourThreadMemory = holder; return(true); } } for (int i = 0; i < start; i++) { holder = blocks[i]; if (holder == null) { break; } if (holder.TryReserve()) { ourThreadMemory = holder; return(true); } } holder = null; return(false); } bool AllocateNew(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); } }
internal Cookie([NotNull] ThreadMemoryHolder holder, bool causedAllocation = false) { myHolder = holder ?? throw new ArgumentNullException(nameof(holder)); CausedAllocation = causedAllocation; }