Files

140 lines
2.5 KiB
C#
Raw Permalink Normal View History

2026-08-27 10:56:38 -06:00
using System;
namespace ProtoBuf;
internal sealed class BufferPool
{
private class CachedBuffer
{
private readonly WeakReference _reference;
public int Size { get; }
public bool IsAlive => _reference.IsAlive;
public byte[] Buffer => (byte[])_reference.Target;
public CachedBuffer(byte[] buffer)
{
Size = buffer.Length;
_reference = new WeakReference(buffer);
}
}
private const int POOL_SIZE = 20;
internal const int BUFFER_LENGTH = 1024;
private static readonly CachedBuffer[] Pool = new CachedBuffer[20];
private const int MaxByteArraySize = 2147483591;
internal static void Flush()
{
lock (Pool)
{
for (int i = 0; i < Pool.Length; i++)
{
Pool[i] = null;
}
}
}
private BufferPool()
{
}
internal static byte[] GetBuffer()
{
return GetBuffer(1024);
}
internal static byte[] GetBuffer(int minSize)
{
byte[] cachedBuffer = GetCachedBuffer(minSize);
return cachedBuffer ?? new byte[minSize];
}
internal static byte[] GetCachedBuffer(int minSize)
{
lock (Pool)
{
int num = -1;
byte[] array = null;
for (int i = 0; i < Pool.Length; i++)
{
CachedBuffer cachedBuffer = Pool[i];
if (cachedBuffer != null && cachedBuffer.Size >= minSize && (array == null || array.Length >= cachedBuffer.Size))
{
byte[] buffer = cachedBuffer.Buffer;
if (buffer == null)
{
Pool[i] = null;
continue;
}
array = buffer;
num = i;
}
}
if (num >= 0)
{
Pool[num] = null;
}
return array;
}
}
internal static void ResizeAndFlushLeft(ref byte[] buffer, int toFitAtLeastBytes, int copyFromIndex, int copyBytes)
{
int num = buffer.Length * 2;
if (num < 0)
{
num = 2147483591;
}
if (num < toFitAtLeastBytes)
{
num = toFitAtLeastBytes;
}
if (copyBytes == 0)
{
ReleaseBufferToPool(ref buffer);
}
byte[] array = GetCachedBuffer(toFitAtLeastBytes) ?? new byte[num];
if (copyBytes > 0)
{
Buffer.BlockCopy(buffer, copyFromIndex, array, 0, copyBytes);
ReleaseBufferToPool(ref buffer);
}
buffer = array;
}
internal static void ReleaseBufferToPool(ref byte[] buffer)
{
if (buffer == null)
{
return;
}
lock (Pool)
{
int num = 0;
int num2 = int.MaxValue;
for (int i = 0; i < Pool.Length; i++)
{
CachedBuffer cachedBuffer = Pool[i];
if (cachedBuffer == null || !cachedBuffer.IsAlive)
{
num = 0;
break;
}
if (cachedBuffer.Size < num2)
{
num = i;
num2 = cachedBuffer.Size;
}
}
Pool[num] = new CachedBuffer(buffer);
}
buffer = null;
}
}