using System;
using System.Collections.Generic;
using MLAPI.Logging;
namespace MLAPI.Serialization.Pooled
{
///
/// Static class containing PooledNetworkBuffers
///
public static class NetworkBufferPool
{
private static uint s_CreatedBuffers = 0;
private static Queue s_OverflowBuffers = new Queue();
private static Queue s_Buffers = new Queue();
private const uint k_MaxBitPoolBuffers = 1024;
private const uint k_MaxCreatedDelta = 768;
///
/// Retrieves an expandable PooledNetworkBuffer from the pool
///
/// An expandable PooledNetworkBuffer
public static PooledNetworkBuffer GetBuffer()
{
if (s_Buffers.Count == 0)
{
if (s_OverflowBuffers.Count > 0)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
{
NetworkLog.LogInfo($"Retrieving {nameof(PooledNetworkBuffer)} from overflow pool. Recent burst?");
}
object weakBuffer = null;
while (s_OverflowBuffers.Count > 0 && ((weakBuffer = s_OverflowBuffers.Dequeue().Target) == null)) ;
if (weakBuffer != null)
{
PooledNetworkBuffer strongBuffer = (PooledNetworkBuffer)weakBuffer;
strongBuffer.SetLength(0);
strongBuffer.Position = 0;
return strongBuffer;
}
}
if (s_CreatedBuffers == k_MaxBitPoolBuffers)
{
if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) NetworkLog.LogWarning($"{k_MaxBitPoolBuffers} buffers have been created. Did you forget to dispose?");
}
else if (s_CreatedBuffers < k_MaxBitPoolBuffers) s_CreatedBuffers++;
return new PooledNetworkBuffer();
}
PooledNetworkBuffer buffer = s_Buffers.Dequeue();
buffer.SetLength(0);
buffer.Position = 0;
return buffer;
}
///
/// Puts a PooledNetworkBuffer back into the pool
///
/// The buffer to put in the pool
public static void PutBackInPool(PooledNetworkBuffer buffer)
{
if (s_Buffers.Count > k_MaxCreatedDelta)
{
// The user just created lots of buffers without returning them in between.
// Buffers are essentially byte array wrappers. This is valuable memory.
// Thus we put this buffer as a weak reference incase of another burst
// But still leave it to GC
if (NetworkLog.CurrentLogLevel <= LogLevel.Developer)
{
NetworkLog.LogInfo($"Putting {nameof(PooledNetworkBuffer)} into overflow pool. Did you forget to dispose?");
}
s_OverflowBuffers.Enqueue(new WeakReference(buffer));
}
else
{
s_Buffers.Enqueue(buffer);
}
}
}
}