namespace Cryville.Common.Buffers { /// /// A resource pool that allows reusing instances of arrays of type . /// /// The item type of the arrays in the pool. public class ArrayPool { private class Bucket : ObjectPool { readonly int _size; public Bucket(int size, int capacity) : base(capacity) { _size = size; } protected override T[] Construct() { return new T[_size]; } } Bucket[] _buckets; /// /// Creates an instance of the class with the default maximum list size and bucket capacity. /// public ArrayPool() : this(0x40000000, 256) { } /// /// Creates an instance of the class. /// /// The maximum size of the arrays in the pool. /// The capacity of each bucket. The pool groups arrays of similar sizes into buckets for faster access. public ArrayPool(int maxSize, int capacityPerBucket) { if (maxSize < 16) maxSize = 16; int num = GetID(maxSize) + 1; _buckets = new Bucket[num]; for (int i = 0; i < num; i++) { _buckets[i] = new Bucket(GetSize(i), capacityPerBucket); } } /// /// Rents an array that is at least the specified size from the pool. /// /// The minimum size of the array. /// An array of type that is at least the specified size. public T[] Rent(int size) { int len2 = size; if (len2 < 16) len2 = 16; var arr = _buckets[GetID(len2)].Rent(); return arr; } /// /// Returns a rented array to the pool. /// /// The array to return. public void Return(T[] arr) { int len2 = arr.Length; if (len2 < 16) len2 = 16; _buckets[GetID(len2)].Return(arr); } static int GetID(int size) { size -= 1; size >>= 4; int num = 0; for (; size != 0; size >>= 1) num++; return num; } static int GetSize(int id) { return 0x10 << id; } } }