66 lines
2.1 KiB
C#
66 lines
2.1 KiB
C#
namespace Cryville.Common.Buffers {
|
|
/// <summary>
|
|
/// A resource pool that allows reusing instances of arrays of type <typeparamref name="T" />.
|
|
/// </summary>
|
|
/// <typeparam name="T">The item type of the arrays in the pool.</typeparam>
|
|
public class ArrayPool<T> {
|
|
private class Bucket : ObjectPool<T[]> {
|
|
readonly int _size;
|
|
public Bucket(int size, int capacity) : base(capacity) {
|
|
_size = size;
|
|
}
|
|
protected override T[] Construct() {
|
|
return new T[_size];
|
|
}
|
|
}
|
|
readonly Bucket[] _buckets;
|
|
/// <summary>
|
|
/// Creates an instance of the <see cref="ArrayPool{T}" /> class with the default maximum list size and bucket capacity.
|
|
/// </summary>
|
|
public ArrayPool() : this(0x40000000, 256) { }
|
|
/// <summary>
|
|
/// Creates an instance of the <see cref="ArrayPool{T}" /> class.
|
|
/// </summary>
|
|
/// <param name="maxSize">The maximum size of the arrays in the pool.</param>
|
|
/// <param name="capacityPerBucket">The capacity of each bucket. The pool groups arrays of similar sizes into buckets for faster access.</param>
|
|
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);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Rents an array that is at least the specified size from the pool.
|
|
/// </summary>
|
|
/// <param name="size">The minimum size of the array.</param>
|
|
/// <returns>An array of type <see cref="T" /> that is at least the specified size.</returns>
|
|
public T[] Rent(int size) {
|
|
int len2 = size;
|
|
if (len2 < 16) len2 = 16;
|
|
var arr = _buckets[GetID(len2)].Rent();
|
|
return arr;
|
|
}
|
|
/// <summary>
|
|
/// Returns a rented array to the pool.
|
|
/// </summary>
|
|
/// <param name="arr">The array to return.</param>
|
|
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;
|
|
}
|
|
}
|
|
}
|