aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/structs/pool.js
diff options
context:
space:
mode:
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/structs/pool.js')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/pool.js381
1 files changed, 381 insertions, 0 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/pool.js b/contexts/data/lib/closure-library/closure/goog/structs/pool.js
new file mode 100644
index 0000000..ba69dd0
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/pool.js
@@ -0,0 +1,381 @@
+// Copyright 2006 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.
+ * When an object is released, it is attempted to be reused.
+ */
+
+
+goog.provide('goog.structs.Pool');
+
+goog.require('goog.Disposable');
+goog.require('goog.structs.Queue');
+goog.require('goog.structs.Set');
+
+
+
+/**
+ * A generic pool class. If min is greater than max, an error is thrown.
+ * @param {number=} opt_minCount Min. number of objects (Default: 1).
+ * @param {number=} opt_maxCount Max. number of objects (Default: 10).
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.structs.Pool = function(opt_minCount, opt_maxCount) {
+ goog.Disposable.call(this);
+
+ /**
+ * Minimum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.minCount_ = opt_minCount || 0;
+
+ /**
+ * Maximum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.maxCount_ = opt_maxCount || 10;
+
+ // Make sure that the max and min constraints are valid.
+ if (this.minCount_ > this.maxCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+
+ /**
+ * Set used to store objects that are currently in the pool and available
+ * to be used.
+ * @type {goog.structs.Queue}
+ * @private
+ */
+ this.freeQueue_ = new goog.structs.Queue();
+
+ /**
+ * Set used to store objects that are currently in the pool and in use.
+ * @type {goog.structs.Set}
+ * @private
+ */
+ this.inUseSet_ = new goog.structs.Set();
+
+ /**
+ * The minimum delay between objects being made available, in milliseconds. If
+ * this is 0, no minimum delay is enforced.
+ * @type {number}
+ * @protected
+ */
+ this.delay = 0;
+
+ /**
+ * The time of the last object being made available, in milliseconds since the
+ * epoch (i.e., the result of Date#toTime). If this is null, no access has
+ * occurred yet.
+ * @type {number?}
+ * @protected
+ */
+ this.lastAccess = null;
+
+ // Make sure that the minCount constraint is satisfied.
+ this.adjustForMinMax();
+
+
+ // TODO(user): Remove once JSCompiler's undefined properties warnings
+ // don't error for guarded properties.
+ var magicProps = {canBeReused: 0};
+};
+goog.inherits(goog.structs.Pool, goog.Disposable);
+
+
+/**
+ * Error to throw when the max/min constraint is attempted to be invalidated.
+ * I.e., when it is attempted for maxCount to be less than minCount.
+ * @type {string}
+ * @private
+ */
+goog.structs.Pool.ERROR_MIN_MAX_ =
+ '[goog.structs.Pool] Min can not be greater than max';
+
+
+/**
+ * Error to throw when the Pool is attempted to be disposed and it is asked to
+ * make sure that there are no objects that are in use (i.e., haven't been
+ * released).
+ * @type {string}
+ * @private
+ */
+goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_ =
+ '[goog.structs.Pool] Objects not released';
+
+
+/**
+ * Sets the minimum count of the pool.
+ * If min is greater than the max count of the pool, an error is thrown.
+ * @param {number} min The minimum count of the pool.
+ */
+goog.structs.Pool.prototype.setMinimumCount = function(min) {
+ // Check count constraints.
+ if (min > this.maxCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+ this.minCount_ = min;
+
+ // Adjust the objects in the pool as needed.
+ this.adjustForMinMax();
+};
+
+
+/**
+ * Sets the maximum count of the pool.
+ * If max is less than the max count of the pool, an error is thrown.
+ * @param {number} max The maximium count of the pool.
+ */
+goog.structs.Pool.prototype.setMaximumCount = function(max) {
+ // Check count constraints.
+ if (max < this.minCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+ this.maxCount_ = max;
+
+ // Adjust the objects in the pool as needed.
+ this.adjustForMinMax();
+};
+
+
+/**
+ * Sets the minimum delay between objects being returned by getObject, in
+ * milliseconds. This defaults to zero, meaning that no minimum delay is
+ * enforced and objects may be used as soon as they're available.
+ * @param {number} delay The minimum delay, in milliseconds.
+ */
+goog.structs.Pool.prototype.setDelay = function(delay) {
+ this.delay = delay;
+};
+
+
+/**
+ * @return {Object|undefined} A new object from the pool if there is one
+ * available, otherwise undefined.
+ */
+goog.structs.Pool.prototype.getObject = function() {
+ var time = goog.now();
+ if (goog.isDefAndNotNull(this.lastAccess) &&
+ time - this.lastAccess < this.delay) {
+ return undefined;
+ }
+
+ var obj = this.removeFreeObject_();
+ if (obj) {
+ this.lastAccess = time;
+ this.inUseSet_.add(obj);
+ }
+
+ return obj;
+};
+
+
+/**
+ * Returns an object to the pool of available objects so that it can be reused.
+ * @param {Object} obj The object to return to the pool of free objects.
+ * @return {boolean} Whether the object was found in the Pool's set of in-use
+ * objects (in other words, whether any action was taken).
+ */
+goog.structs.Pool.prototype.releaseObject = function(obj) {
+ if (this.inUseSet_.remove(obj)) {
+ this.addFreeObject(obj);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a free object from the collection of objects that are free so that it
+ * can be used.
+ *
+ * NOTE: This method does not mark the returned object as in use.
+ *
+ * @return {Object|undefined} The object removed from the free collection, if
+ * there is one available. Otherwise, undefined.
+ * @private
+ */
+goog.structs.Pool.prototype.removeFreeObject_ = function() {
+ var obj;
+ while (this.getFreeCount() > 0) {
+ obj = /** @type {Object} */(this.freeQueue_.dequeue());
+
+ if (!this.objectCanBeReused(obj)) {
+ this.adjustForMinMax();
+ } else {
+ break;
+ }
+ }
+
+ if (!obj && this.getCount() < this.maxCount_) {
+ obj = this.createObject();
+ }
+
+ return obj;
+};
+
+
+/**
+ * Adds an object to the collection of objects that are free. If the object can
+ * not be added, then it is disposed.
+ *
+ * @param {Object} obj The object to add to collection of free objects.
+ */
+goog.structs.Pool.prototype.addFreeObject = function(obj) {
+ this.inUseSet_.remove(obj);
+ if (this.objectCanBeReused(obj) && this.getCount() < this.maxCount_) {
+ this.freeQueue_.enqueue(obj);
+ } else {
+ this.disposeObject(obj);
+ }
+};
+
+
+/**
+ * Adjusts the objects held in the pool to be within the min/max constraints.
+ *
+ * NOTE: It is possible that the number of objects in the pool will still be
+ * greater than the maximum count of objects allowed. This will be the case
+ * if no more free objects can be disposed of to get below the minimum count
+ * (i.e., all objects are in use).
+ */
+goog.structs.Pool.prototype.adjustForMinMax = function() {
+ var freeQueue = this.freeQueue_;
+
+ // Make sure the at least the minimum number of objects are created.
+ while (this.getCount() < this.minCount_) {
+ freeQueue.enqueue(this.createObject());
+ }
+
+ // Make sure no more than the maximum number of objects are created.
+ while (this.getCount() > this.maxCount_ && this.getFreeCount() > 0) {
+ this.disposeObject(/** @type {Object} */(freeQueue.dequeue()));
+ }
+};
+
+
+/**
+ * Should be overriden by sub-classes to return an instance of the object type
+ * that is expected in the pool.
+ * @return {Object} The created object.
+ */
+goog.structs.Pool.prototype.createObject = function() {
+ return {};
+};
+
+
+/**
+ * Should be overriden to dispose of an object. Default implementation is to
+ * remove all its members, which should render it useless. Calls the object's
+ * {@code dispose()} method, if available.
+ * @param {Object} obj The object to dispose.
+ */
+goog.structs.Pool.prototype.disposeObject = function(obj) {
+ if (typeof obj.dispose == 'function') {
+ obj.dispose();
+ } else {
+ for (var i in obj) {
+ obj[i] = null;
+ }
+ }
+};
+
+
+/**
+ * Should be overriden to determine whether an object has become unusable and
+ * should not be returned by getObject(). Calls the object's
+ * {@code canBeReused()} method, if available.
+ * @param {Object} obj The object to test.
+ * @return {boolean} Whether the object can be reused.
+ */
+goog.structs.Pool.prototype.objectCanBeReused = function(obj) {
+ if (typeof obj.canBeReused == 'function') {
+ return obj.canBeReused();
+ }
+ return true;
+};
+
+
+/**
+ * Returns true if the given object is in the pool.
+ * @param {Object} obj The object to check the pool for.
+ * @return {boolean} Whether the pool contains the object.
+ */
+goog.structs.Pool.prototype.contains = function(obj) {
+ return this.freeQueue_.contains(obj) || this.inUseSet_.contains(obj);
+};
+
+
+/**
+ * Returns the number of objects currently in the pool.
+ * @return {number} Number of objects currently in the pool.
+ */
+goog.structs.Pool.prototype.getCount = function() {
+ return this.freeQueue_.getCount() + this.inUseSet_.getCount();
+};
+
+
+/**
+ * Returns the number of objects currently in use in the pool.
+ * @return {number} Number of objects currently in use in the pool.
+ */
+goog.structs.Pool.prototype.getInUseCount = function() {
+ return this.inUseSet_.getCount();
+};
+
+
+/**
+ * Returns the number of objects currently free in the pool.
+ * @return {number} Number of objects currently free in the pool.
+ */
+goog.structs.Pool.prototype.getFreeCount = function() {
+ return this.freeQueue_.getCount();
+};
+
+
+/**
+ * Determines if the pool contains no objects.
+ * @return {boolean} Whether the pool contains no objects.
+ */
+goog.structs.Pool.prototype.isEmpty = function() {
+ return this.freeQueue_.isEmpty() && this.inUseSet_.isEmpty();
+};
+
+
+/**
+ * Disposes of the pool and all objects currently held in the pool.
+ * @override
+ * @protected
+ */
+goog.structs.Pool.prototype.disposeInternal = function() {
+ goog.structs.Pool.superClass_.disposeInternal.call(this);
+ if (this.getInUseCount() > 0) {
+ throw Error(goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_);
+ }
+ delete this.inUseSet_;
+
+ // Call disposeObject on each object held by the pool.
+ var freeQueue = this.freeQueue_;
+ while (!freeQueue.isEmpty()) {
+ this.disposeObject(/** @type {Object} */ (freeQueue.dequeue()));
+ }
+ delete this.freeQueue_;
+};