using System;
using System.Buffers;
namespace Ryujinx.Common.Pools
{
///
/// A centralized, static pool for getting multipurpose buffers of any type.
/// "But why does this exist when you have ?" This actually just wraps around
/// ArrayPool. The difference is that the rented array is hidden inside of a
/// handle and is only exposed as a . This makes it harder to leak references to the
/// pooled array, which makes it a bit easier to track ownership. The PooledBuffer handle is
/// so code analysis can enforce better practice as well. In addition, it also tracks the initial requested
/// size of the allocated buffer, so you can pass it around and users of it know how much of the data
/// is actually valid, compared to ArrayPool which just gives you an arbitrary sized array.
///
public static class BufferPool
{
public const int DEFAULT_BUFFER_SIZE = 65536;
private static readonly PooledBuffer EMPTY_POOLED_BUFFER = new PooledBuffer(Array.Empty(), -1);
///
/// Returns a disposable instance backed by a contiguous array of at least the requested number of elements.
/// The internal array is only exposed as a to prevent user code from storing references to it outside
/// of the potential lifetime of the pooled handle.
///
/// The minimum number of elements that you require
/// Whether to clear the contents of the buffer before returning. If false (by default), the buffer may initially contain garbage.
/// A pooled buffer of exactly the requested size.
public static PooledBuffer Rent(int minimumRequestedSize = DEFAULT_BUFFER_SIZE, bool clearArray = false)
{
if (minimumRequestedSize < 0)
{
throw new ArgumentOutOfRangeException("Requested buffer size must be a positive number");
}
if (minimumRequestedSize == 0)
{
return EMPTY_POOLED_BUFFER;
}
T[] array = ArrayPool.Shared.Rent(minimumRequestedSize);
if (clearArray)
{
Array.Clear(array, 0, minimumRequestedSize);
}
PooledBuffer returnVal = new PooledBuffer(array, minimumRequestedSize);
#if TRACK_BUFFERPOOL_LEAKS
returnVal.MarkRented();
#endif
return returnVal;
}
}
}