internal void ReturnLargeBuffer(byte[] buffer, string tag)
{
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
if (!this.IsLargeBufferMultiple(buffer.Length))
{
throw new ArgumentException(
"buffer did not originate from this memory manager. The size is not a multiple of " +
this.LargeBufferMultiple);
}
var poolIndex = buffer.Length / this.largeBufferMultiple - 1;
if (poolIndex < this.largePools.Length)
{
if ((this.largePools[poolIndex].Count + 1) * buffer.Length <= this.MaximumFreeLargePoolBytes ||
this.MaximumFreeLargePoolBytes == 0)
{
this.largePools[poolIndex].Push(buffer);
Interlocked.Add(ref this.largeBufferFreeSize[poolIndex], buffer.Length);
}
else
{
Events.Write.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Large, tag,
Events.MemoryStreamDiscardReason.EnoughFree);
if (this.LargeBufferDiscarded != null)
{
this.LargeBufferDiscarded(Events.MemoryStreamDiscardReason.EnoughFree);
}
}
}
else
{
// This is a non-poolable buffer, but we still want to track its size for inuse
// analysis. We have space in the inuse array for this.
poolIndex = this.largeBufferInUseSize.Length - 1;
Events.Write.MemoryStreamDiscardBuffer(Events.MemoryStreamBufferType.Large, tag,
Events.MemoryStreamDiscardReason.TooLarge);
if (this.LargeBufferDiscarded != null)
{
this.LargeBufferDiscarded(Events.MemoryStreamDiscardReason.TooLarge);
}
}
Interlocked.Add(ref this.largeBufferInUseSize[poolIndex], -buffer.Length);
if (this.UsageReport != null)
{
this.UsageReport(this.smallPoolInUseSize, this.smallPoolFreeSize, this.LargePoolInUseSize,
this.LargePoolFreeSize);
}
}