Skip to content

Instantly share code, notes, and snippets.

@AimWhy
Created March 2, 2025 01:00
Show Gist options
  • Save AimWhy/5b8cf8385d0e32ba66d91e8a5770cd7c to your computer and use it in GitHub Desktop.
Save AimWhy/5b8cf8385d0e32ba66d91e8a5770cd7c to your computer and use it in GitHub Desktop.
export interface IDisposable {
dispose(): void;
}
export interface IReference<T> extends IDisposable {
readonly object: T;
}
export interface IObjectData {
getId(): unknown;
}
export interface IPooledObject<TData> extends IDisposable {
setData(data: TData): void;
}
export class ObjectPool<TData extends IObjectData, T extends IPooledObject<TData>> implements IDisposable {
private readonly _unused = new Set<T>();
private readonly _used = new Set<T>();
private readonly _itemData = new Map<T, TData>();
constructor(
private readonly _create: (data: TData) => T,
private readonly retain: number = 5
) { }
public getUnusedObj(data: TData): IReference<T> {
let obj: T;
if (this._unused.size === 0) {
obj = this._create(data);
this._itemData.set(obj, data);
} else {
const values = [...this._unused.values()];
obj = values.find(obj => this._itemData.get(obj)!.getId() === data.getId()) ?? values[0];
this._unused.delete(obj);
this._itemData.set(obj, data);
obj.setData(data);
}
this._used.add(obj);
return {
object: obj,
dispose: () => {
this._used.delete(obj);
if (this._unused.size > this.retain) {
obj.dispose();
} else {
this._unused.add(obj);
}
}
};
}
dispose(): void {
for (const obj of this._used) {
obj.dispose();
}
for (const obj of this._unused) {
obj.dispose();
}
this._used.clear();
this._unused.clear();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment