using System.Collections.Generic;
namespace Cryville.Common.Buffers {
///
/// A resource pool that allows reusing instances of lists of type .
///
/// The item type of the lists in the pool.
public class ListPool {
private class Bucket : ObjectPool> {
readonly int _size;
public Bucket(int size, int capacity) : base(capacity) {
_size = size;
}
protected override List Construct() {
return new List(_size);
}
}
readonly Bucket[] _buckets;
///
/// Creates an instance of the class with the default maximum list size and bucket capacity.
///
public ListPool() : this(0x40000000, 256) { }
///
/// Creates an instance of the class.
///
/// The maximum size of the lists in the pool.
/// The capacity of each bucket. The pool groups lists of similar sizes into buckets for faster access.
public ListPool(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 a list of the specified size from the pool. The size of the list must not be changed when it is rented.
///
/// The size of the list.
/// A of the specified size.
public List Rent(int size) {
int len2 = size;
if (len2 < 16) len2 = 16;
var list = _buckets[GetID(len2)].Rent();
if (list.Count < size)
for (int i = list.Count; i < size; i++) list.Add(default(T));
else if (list.Count > size)
list.RemoveRange(size, list.Count - size);
return list;
}
///
/// Returns a rented list to the pool.
///
/// The list to return.
public void Return(List list) {
int len2 = list.Capacity;
if (len2 < 16) len2 = 16;
_buckets[GetID(len2)].Return(list);
}
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;
}
}
}