mirror of https://github.com/quasar/Quasar.git
103 lines
3.1 KiB
C#
103 lines
3.1 KiB
C#
|
|
using System.Threading;
|
|
namespace ProtoBuf
|
|
{
|
|
internal sealed class BufferPool
|
|
{
|
|
internal static void Flush()
|
|
{
|
|
#if PLAT_NO_INTERLOCKED
|
|
lock(pool)
|
|
{
|
|
for (int i = 0; i < pool.Length; i++) pool[i] = null;
|
|
}
|
|
#else
|
|
for (int i = 0; i < pool.Length; i++)
|
|
{
|
|
Interlocked.Exchange(ref pool[i], null); // and drop the old value on the floor
|
|
}
|
|
#endif
|
|
}
|
|
private BufferPool() { }
|
|
const int PoolSize = 20;
|
|
internal const int BufferLength = 1024;
|
|
private static readonly object[] pool = new object[PoolSize];
|
|
|
|
internal static byte[] GetBuffer()
|
|
{
|
|
object tmp;
|
|
#if PLAT_NO_INTERLOCKED
|
|
lock(pool)
|
|
{
|
|
for (int i = 0; i < pool.Length; i++)
|
|
{
|
|
if((tmp = pool[i]) != null)
|
|
{
|
|
pool[i] = null;
|
|
return (byte[])tmp;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
for (int i = 0; i < pool.Length; i++)
|
|
{
|
|
if ((tmp = Interlocked.Exchange(ref pool[i], null)) != null) return (byte[])tmp;
|
|
}
|
|
#endif
|
|
return new byte[BufferLength];
|
|
}
|
|
internal static void ResizeAndFlushLeft(ref byte[] buffer, int toFitAtLeastBytes, int copyFromIndex, int copyBytes)
|
|
{
|
|
Helpers.DebugAssert(buffer != null);
|
|
Helpers.DebugAssert(toFitAtLeastBytes > buffer.Length);
|
|
Helpers.DebugAssert(copyFromIndex >= 0);
|
|
Helpers.DebugAssert(copyBytes >= 0);
|
|
|
|
// try doubling, else match
|
|
int newLength = buffer.Length * 2;
|
|
if (newLength < toFitAtLeastBytes) newLength = toFitAtLeastBytes;
|
|
|
|
byte[] newBuffer = new byte[newLength];
|
|
if (copyBytes > 0)
|
|
{
|
|
Helpers.BlockCopy(buffer, copyFromIndex, newBuffer, 0, copyBytes);
|
|
}
|
|
if (buffer.Length == BufferPool.BufferLength)
|
|
{
|
|
BufferPool.ReleaseBufferToPool(ref buffer);
|
|
}
|
|
buffer = newBuffer;
|
|
}
|
|
internal static void ReleaseBufferToPool(ref byte[] buffer)
|
|
{
|
|
if (buffer == null) return;
|
|
if (buffer.Length == BufferLength)
|
|
{
|
|
#if PLAT_NO_INTERLOCKED
|
|
lock (pool)
|
|
{
|
|
for (int i = 0; i < pool.Length; i++)
|
|
{
|
|
if(pool[i] == null)
|
|
{
|
|
pool[i] = buffer;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
for (int i = 0; i < pool.Length; i++)
|
|
{
|
|
if (Interlocked.CompareExchange(ref pool[i], buffer, null) == null)
|
|
{
|
|
break; // found a null; swapped it in
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
// if no space, just drop it on the floor
|
|
buffer = null;
|
|
}
|
|
|
|
}
|
|
} |