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; } } }