blob: ff400fccbc3b8b7a7484a65de082af88a4a9651d [file] [log] [blame]
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @fileoverview Datastructure: Pool.
*
*
* A generic class for handling pools of objects that is more efficient than
* goog.structs.Pool because it doesn't maintain a list of objects that are in
* use. See constructor comment.
*/
goog.provide('goog.structs.SimplePool');
goog.require('goog.Disposable');
/**
* A generic pool class. Simpler and more efficient than goog.structs.Pool
* because it doesn't maintain a list of objects that are in use. This class
* has constant overhead and doesn't create any additional objects as part of
* the pool management after construction time.
*
* IMPORTANT: If the objects being pooled are arrays or maps that can have
* unlimited number of properties, they need to be cleaned before being
* returned to the pool.
*
* Also note that {@see goog.object.clean} actually allocates an array to clean
* the object passed to it, so simply using this function would defy the
* purpose of using the pool.
*
* @param {number} initialCount Initial number of objects to populate the free
* pool at construction time.
* @param {number} maxCount Maximum number of objects to keep in the free pool.
* @constructor
* @extends {goog.Disposable}
* @template T
*/
goog.structs.SimplePool = function(initialCount, maxCount) {
goog.Disposable.call(this);
/**
* Function for overriding createObject. The avoids a common case requiring
* subclassing this class.
* @private {Function}
*/
this.createObjectFn_ = null;
/**
* Function for overriding disposeObject. The avoids a common case requiring
* subclassing this class.
* @private {Function}
*/
this.disposeObjectFn_ = null;
/**
* Maximum number of objects allowed
* @private {number}
*/
this.maxCount_ = maxCount;
/**
* Queue used to store objects that are currently in the pool and available
* to be used.
* @private {Array<T>}
*/
this.freeQueue_ = [];
this.createInitial_(initialCount);
};
goog.inherits(goog.structs.SimplePool, goog.Disposable);
/**
* Sets the {@code createObject} function which is used for creating a new
* object in the pool.
* @param {Function} createObjectFn Create object function which returns the
* newly created object.
*/
goog.structs.SimplePool.prototype.setCreateObjectFn = function(createObjectFn) {
this.createObjectFn_ = createObjectFn;
};
/**
* Sets the {@code disposeObject} function which is used for disposing of an
* object in the pool.
* @param {Function} disposeObjectFn Dispose object function which takes the
* object to dispose as a parameter.
*/
goog.structs.SimplePool.prototype.setDisposeObjectFn = function(
disposeObjectFn) {
this.disposeObjectFn_ = disposeObjectFn;
};
/**
* Gets an unused object from the the pool, if there is one available,
* otherwise creates a new one.
* @return {T} An object from the pool or a new one if necessary.
*/
goog.structs.SimplePool.prototype.getObject = function() {
if (this.freeQueue_.length) {
return this.freeQueue_.pop();
}
return this.createObject();
};
/**
* Returns an object to the pool so that it can be reused. If the pool is
* already full, the object is disposed instead.
* @param {T} obj The object to release.
*/
goog.structs.SimplePool.prototype.releaseObject = function(obj) {
if (this.freeQueue_.length < this.maxCount_) {
this.freeQueue_.push(obj);
} else {
this.disposeObject(obj);
}
};
/**
* Populates the pool with initialCount objects.
* @param {number} initialCount The number of objects to add to the pool.
* @private
*/
goog.structs.SimplePool.prototype.createInitial_ = function(initialCount) {
if (initialCount > this.maxCount_) {
throw Error('[goog.structs.SimplePool] Initial cannot be greater than max');
}
for (var i = 0; i < initialCount; i++) {
this.freeQueue_.push(this.createObject());
}
};
/**
* Should be overridden by sub-classes to return an instance of the object type
* that is expected in the pool.
* @return {T} The created object.
*/
goog.structs.SimplePool.prototype.createObject = function() {
if (this.createObjectFn_) {
return this.createObjectFn_();
} else {
return {};
}
};
/**
* Should be overrideen to dispose of an object. Default implementation is to
* remove all of the object's members, which should render it useless. Calls the
* object's dispose method, if available.
* @param {T} obj The object to dispose.
*/
goog.structs.SimplePool.prototype.disposeObject = function(obj) {
if (this.disposeObjectFn_) {
this.disposeObjectFn_(obj);
} else if (goog.isObject(obj)) {
if (goog.isFunction(obj.dispose)) {
obj.dispose();
} else {
for (var i in obj) {
delete obj[i];
}
}
}
};
/**
* Disposes of the pool and all objects currently held in the pool.
* @override
* @protected
*/
goog.structs.SimplePool.prototype.disposeInternal = function() {
goog.structs.SimplePool.superClass_.disposeInternal.call(this);
// Call disposeObject on each object held by the pool.
var freeQueue = this.freeQueue_;
while (freeQueue.length) {
this.disposeObject(freeQueue.pop());
}
delete this.freeQueue_;
};