/**
* A generic class for managing a pool of items.
* @template T The type of items in the pool. Must implement PoolItem.
* @memberof utils
*/
export class Pool<T extends PoolItem>
{
public readonly _classType: PoolItemConstructor<T>;
private readonly _pool: T[] = [];
private _count = 0;
private _index = 0;
/**
* Constructs a new Pool.
* @param ClassType - The constructor of the items in the pool.
* @param {number} [initialSize] - The initial size of the pool.
*/
constructor(ClassType: PoolItemConstructor<T>, initialSize?: number)
{
this._classType = ClassType;
if (initialSize)
{
this.prepopulate(initialSize);
}
}
/**
* Prepopulates the pool with a given number of items.
* @param total - The number of items to add to the pool.
*/
public prepopulate(total: number): void
{
for (let i = 0; i < total; i++)
{
this._pool[this._index++] = new this._classType();
}
this._count += total;
}
/**
* Gets an item from the pool. Calls the item's `init` method if it exists.
* If there are no items left in the pool, a new one will be created.
* @param {unknown} [data] - Optional data to pass to the item's constructor.
* @returns {T} The item from the pool.
*/
public get(data?: unknown): T
{
let item;
if (this._index > 0)
{
item = this._pool[--this._index];
}
else
{
item = new this._classType();
}
item.init?.(data);
return item;
}
/**
* Returns an item to the pool. Calls the item's `reset` method if it exists.
* @param {T} item - The item to return to the pool.
*/
public return(item: T): void
{
item.reset?.();
this._pool[this._index++] = item;
}
/**
* Gets the number of items in the pool.
* @readonly
* @member {number}
*/
get totalSize(): number
{
return this._count;
}
/**
* Gets the number of items in the pool that are free to use without needing to create more.
* @readonly
* @member {number}
*/
get totalFree(): number
{
return this._index;
}
/**
* Gets the number of items in the pool that are currently in use.
* @readonly
* @member {number}
*/
get totalUsed(): number
{
return this._count - this._index;
}
}
/**
* An object that can be stored in a Pool.
* @memberof utils
*/
export type PoolItem = {
init?: (data?: any) => void;
reset?: () => void;
[key: string]: any;
};
/**
* The constructor of an object that can be stored in a Pool.
* @typeParam K - The type of the object that can be stored in a Pool.
* @memberof utils
*/
export type PoolItemConstructor<K extends PoolItem> = new () => K;