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