// 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} */ 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_; };