src/core/Pool.js
import PUID from '../utils/PUID';
import { CORE_TYPE_POOL as type } from './types';
/**
* An object pool implementation. Used for pooling objects to avoid unnecessary
* garbage collection.
*
*/
export default class Pool {
/**
* Constructs a Pool instance.
*
* @return void
*/
constructor() {
/**
* @desc The class type.
* @type {string}
*/
this.type = type;
/**
* @desc Incrementing id that keeps a count of the number of objects created
* @type {integer}
*/
this.cID = 0;
/**
* @desc Map of pools in the format of PUID<String>: pool<Array>
* @type {object}
*/
this.list = {};
}
/**
* Attempts to create a new object either by creating a new instance or calling its
* clone method.
*
* TODO COVERAGE - for the constructorArgs
* @param {function|object} functionOrObject - The object to instantiate or clone
* @return {object|undefined}
*/
create(functionOrObject, ...constructorArgs) {
if (!this.canCreateNewObject(functionOrObject)) {
throw new Error(
'The pool is unable to create or clone the object supplied'
);
}
this.cID++;
if (this.canInstantiateObject(functionOrObject)) {
return new functionOrObject(...constructorArgs);
}
if (this.canCloneObject(functionOrObject)) {
return functionOrObject.clone();
}
}
/**
* Determines if the object is able to be instantiated or not.
*
* @param {object} object - The object to check
* @return {boolean}
*/
canInstantiateObject(object) {
return typeof object === 'function';
}
/**
* Determines if the object is able to be cloned or not.
*
* @param {object} object - The object to check
* @return {boolean}
*/
canCloneObject(object) {
return object.clone && typeof object.clone === 'function';
}
/**
* Determines if a new object is able to be created.
*
* @param {object} object - The object to check
* @return {boolean}
*/
canCreateNewObject(object) {
return this.canInstantiateObject(object) || this.canCloneObject(object)
? true
: false;
}
/**
* Gets a count of all objects in the pool.
*
* @return {integer}
*/
getCount() {
var count = 0;
for (var id in this.list) count += this.list[id].length;
return count++;
}
/**
* Gets an object either by creating a new one or retrieving it from the pool.
*
* @param {function|object} obj - The function or object to get
* @param {array} args - The args to pass to the function on creation
* @return {object}
*/
get(obj, ...args) {
var p,
puid = obj.__puid || PUID.id(obj);
if (this.list[puid] && this.list[puid].length > 0)
p = this.list[puid].pop();
else p = this.create(obj, ...args);
p.__puid = obj.__puid || puid;
return p;
}
/**
* Pushes an object into the pool.
*
* @param {object} obj - The object to expire
* @return {integer}
*/
expire(obj) {
return this._getList(obj.__puid).push(obj);
}
/**
* Destroys all pools.
*
* @return void
*/
destroy() {
for (var id in this.list) {
this.list[id].length = 0;
delete this.list[id];
}
}
/**
* Gets the pool mapped to the UID.
*
* @param {string} uid - The pool uid
* @return {array}
*/
_getList(uid) {
uid = uid || 'default';
if (!this.list[uid]) this.list[uid] = [];
return this.list[uid];
}
}