@nativescript-community/ui-chart
Version:
A powerful chart / graph plugin, supporting line, bar, pie, radar, bubble, and candlestick charts as well as scaling, panning and animations.
183 lines • 6.63 kB
JavaScript
export class Poolable {
constructor() {
this.mCurrentOwnerId = Poolable.mNO_OWNER;
}
}
Poolable.mNO_OWNER = -1;
const WRONG_POOL = 'object_wrong_poolid';
const ALREADY_STORED = 'object_already_stored';
/**
* An object pool for recycling of object instances extending Poolable.
*
*
* Cost/Benefit :
* Cost - The pool can only contain objects extending Poolable.
* Benefit - The pool can very quickly determine if an object is elligable for storage without iteration.
* Benefit - The pool can also know if an instance of Poolable is already stored in a different pool instance.
* Benefit - The pool can grow as needed, if it is empty
* Cost - However, refilling the pool when it is empty might incur a time cost with sufficiently large capacity. Set the replenishPercentage to a lower number if this is a concern.
*
* Created by Tony Patino on 6/20/16.
*/
export class ObjectPool {
/**
* Returns the id of the given pool instance.
*
* @return an integer ID belonging to this pool instance.
*/
getPoolId() {
return this.mPoolId;
}
/**
* Returns an ObjectPool instance, of a given starting capacity, that recycles instances of a given Poolable object.
*
* @param withCapacity A positive integer value.
* @param object An instance of the object that the pool should recycle.
* @return
*/
static create(withCapacity, object) {
const result = new ObjectPool(withCapacity, object);
result.mPoolId = ObjectPool.mIds++;
// ObjectPool.ids++;
return result;
}
constructor(withCapacity, object) {
if (withCapacity <= 0) {
throw new Error('Object Pool must be instantiated with a capacity greater than 0!');
}
this.mDesiredCapacity = withCapacity;
this.mObjects = new Array(this.mDesiredCapacity);
this.mObjectsPointer = 0;
this.mModelObject = object;
this.mReplenishPercentage = 1.0;
this.refillPool();
}
/**
* Set the percentage of the pool to replenish on empty. Valid values are between
* 0.00 and 1.00
*
* @param percentage a value between 0 and 1, representing the percentage of the pool to replenish.
*/
setReplenishPercentage(percentage) {
let p = percentage;
if (p > 1) {
p = 1;
}
else if (p < 0) {
p = 0;
}
this.mReplenishPercentage = p;
return this;
}
getReplenishPercentage() {
return this.mReplenishPercentage;
}
refillPool(percentage) {
if (percentage === undefined) {
this.refillPool(this.mReplenishPercentage);
}
else {
let portionOfCapacity = this.mDesiredCapacity * percentage;
if (portionOfCapacity < 1) {
portionOfCapacity = 1;
}
else if (portionOfCapacity > this.mDesiredCapacity) {
portionOfCapacity = this.mDesiredCapacity;
}
for (let i = 0; i < portionOfCapacity; i++) {
this.mObjects[i] = this.mModelObject.instantiate();
}
this.mObjectsPointer = portionOfCapacity - 1;
}
}
/**
* Returns an instance of Poolable. If get() is called with an empty pool, the pool will be
* replenished. If the pool capacity is sufficiently large, this could come at a performance
* cost.
*
* @return An instance of Poolable object T
*/
get() {
if (this.mObjectsPointer === -1 && this.mReplenishPercentage > 0.0) {
this.refillPool();
}
const result = this.mObjects[this.mObjectsPointer];
result.mCurrentOwnerId = Poolable.mNO_OWNER;
this.mObjectsPointer--;
return result;
}
/**
* Recycle an instance of Poolable that this pool is capable of generating.
* The T instance passed must not already exist inside this or any other ObjectPool instance.
*
* @param object An object of type T to recycle
*/
recycle(object) {
if (Array.isArray(object)) {
while (this.mObjects.length + this.mObjectsPointer + 1 > this.mDesiredCapacity) {
this.resizePool();
}
const objectsListSize = this.mObjects.length;
// Not relying on recycle(T object) because this is more performant.
for (let i = 0; i < objectsListSize; i++) {
const object = this.mObjects[i];
if (object.currentOwnerId !== Poolable.mNO_OWNER) {
if (object.currentOwnerId === this.mPoolId) {
throw new Error(ALREADY_STORED);
}
else {
throw new Error(WRONG_POOL);
}
}
object.currentOwnerId = this.mPoolId;
this.mObjects[this.mObjectsPointer + 1 + i] = object;
}
this.mObjectsPointer += objectsListSize;
}
else {
if (object.mCurrentOwnerId !== Poolable.mNO_OWNER) {
if (object.mCurrentOwnerId === this.mPoolId) {
throw new Error(ALREADY_STORED);
}
else {
throw new Error(WRONG_POOL);
}
}
this.mObjectsPointer++;
if (this.mObjectsPointer >= this.mObjects.length) {
this.resizePool();
}
object.mCurrentOwnerId = this.mPoolId;
this.mObjects[this.mObjectsPointer] = object;
}
}
resizePool() {
const oldCapacity = this.mDesiredCapacity;
this.mDesiredCapacity *= 2;
const temp = new Array(this.mDesiredCapacity);
for (let i = 0; i < oldCapacity; i++) {
temp[i] = this.mObjects[i];
}
this.mObjects = temp;
}
/**
* Returns the capacity of this object pool. Note : The pool will automatically resize
* to contain additional objects if the user tries to add more objects than the pool's
* capacity allows, but this comes at a performance cost.
*
* @return The capacity of the pool.
*/
getPoolCapacity() {
return this.mObjects.length;
}
/**
* Returns the number of objects remaining in the pool, for diagnostic purposes.
*
* @return The number of objects remaining in the pool.
*/
getPoolCount() {
return this.mObjectsPointer + 1;
}
}
ObjectPool.mIds = 0;
//# sourceMappingURL=ObjectPool.js.map