simplepool.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Datastructure: Pool.
  16. *
  17. *
  18. * A generic class for handling pools of objects that is more efficient than
  19. * goog.structs.Pool because it doesn't maintain a list of objects that are in
  20. * use. See constructor comment.
  21. */
  22. goog.provide('goog.structs.SimplePool');
  23. goog.require('goog.Disposable');
  24. /**
  25. * A generic pool class. Simpler and more efficient than goog.structs.Pool
  26. * because it doesn't maintain a list of objects that are in use. This class
  27. * has constant overhead and doesn't create any additional objects as part of
  28. * the pool management after construction time.
  29. *
  30. * IMPORTANT: If the objects being pooled are arrays or maps that can have
  31. * unlimited number of properties, they need to be cleaned before being
  32. * returned to the pool.
  33. *
  34. * Also note that {@see goog.object.clean} actually allocates an array to clean
  35. * the object passed to it, so simply using this function would defy the
  36. * purpose of using the pool.
  37. *
  38. * @param {number} initialCount Initial number of objects to populate the free
  39. * pool at construction time.
  40. * @param {number} maxCount Maximum number of objects to keep in the free pool.
  41. * @constructor
  42. * @extends {goog.Disposable}
  43. * @template T
  44. */
  45. goog.structs.SimplePool = function(initialCount, maxCount) {
  46. goog.Disposable.call(this);
  47. /**
  48. * Function for overriding createObject. The avoids a common case requiring
  49. * subclassing this class.
  50. * @private {Function}
  51. */
  52. this.createObjectFn_ = null;
  53. /**
  54. * Function for overriding disposeObject. The avoids a common case requiring
  55. * subclassing this class.
  56. * @private {Function}
  57. */
  58. this.disposeObjectFn_ = null;
  59. /**
  60. * Maximum number of objects allowed
  61. * @private {number}
  62. */
  63. this.maxCount_ = maxCount;
  64. /**
  65. * Queue used to store objects that are currently in the pool and available
  66. * to be used.
  67. * @private {Array<T>}
  68. */
  69. this.freeQueue_ = [];
  70. this.createInitial_(initialCount);
  71. };
  72. goog.inherits(goog.structs.SimplePool, goog.Disposable);
  73. /**
  74. * Sets the {@code createObject} function which is used for creating a new
  75. * object in the pool.
  76. * @param {Function} createObjectFn Create object function which returns the
  77. * newly created object.
  78. */
  79. goog.structs.SimplePool.prototype.setCreateObjectFn = function(createObjectFn) {
  80. this.createObjectFn_ = createObjectFn;
  81. };
  82. /**
  83. * Sets the {@code disposeObject} function which is used for disposing of an
  84. * object in the pool.
  85. * @param {Function} disposeObjectFn Dispose object function which takes the
  86. * object to dispose as a parameter.
  87. */
  88. goog.structs.SimplePool.prototype.setDisposeObjectFn = function(
  89. disposeObjectFn) {
  90. this.disposeObjectFn_ = disposeObjectFn;
  91. };
  92. /**
  93. * Gets an unused object from the the pool, if there is one available,
  94. * otherwise creates a new one.
  95. * @return {T} An object from the pool or a new one if necessary.
  96. */
  97. goog.structs.SimplePool.prototype.getObject = function() {
  98. if (this.freeQueue_.length) {
  99. return this.freeQueue_.pop();
  100. }
  101. return this.createObject();
  102. };
  103. /**
  104. * Returns an object to the pool so that it can be reused. If the pool is
  105. * already full, the object is disposed instead.
  106. * @param {T} obj The object to release.
  107. */
  108. goog.structs.SimplePool.prototype.releaseObject = function(obj) {
  109. if (this.freeQueue_.length < this.maxCount_) {
  110. this.freeQueue_.push(obj);
  111. } else {
  112. this.disposeObject(obj);
  113. }
  114. };
  115. /**
  116. * Populates the pool with initialCount objects.
  117. * @param {number} initialCount The number of objects to add to the pool.
  118. * @private
  119. */
  120. goog.structs.SimplePool.prototype.createInitial_ = function(initialCount) {
  121. if (initialCount > this.maxCount_) {
  122. throw Error('[goog.structs.SimplePool] Initial cannot be greater than max');
  123. }
  124. for (var i = 0; i < initialCount; i++) {
  125. this.freeQueue_.push(this.createObject());
  126. }
  127. };
  128. /**
  129. * Should be overridden by sub-classes to return an instance of the object type
  130. * that is expected in the pool.
  131. * @return {T} The created object.
  132. */
  133. goog.structs.SimplePool.prototype.createObject = function() {
  134. if (this.createObjectFn_) {
  135. return this.createObjectFn_();
  136. } else {
  137. return {};
  138. }
  139. };
  140. /**
  141. * Should be overrideen to dispose of an object. Default implementation is to
  142. * remove all of the object's members, which should render it useless. Calls the
  143. * object's dispose method, if available.
  144. * @param {T} obj The object to dispose.
  145. */
  146. goog.structs.SimplePool.prototype.disposeObject = function(obj) {
  147. if (this.disposeObjectFn_) {
  148. this.disposeObjectFn_(obj);
  149. } else if (goog.isObject(obj)) {
  150. if (goog.isFunction(obj.dispose)) {
  151. obj.dispose();
  152. } else {
  153. for (var i in obj) {
  154. delete obj[i];
  155. }
  156. }
  157. }
  158. };
  159. /**
  160. * Disposes of the pool and all objects currently held in the pool.
  161. * @override
  162. * @protected
  163. */
  164. goog.structs.SimplePool.prototype.disposeInternal = function() {
  165. goog.structs.SimplePool.superClass_.disposeInternal.call(this);
  166. // Call disposeObject on each object held by the pool.
  167. var freeQueue = this.freeQueue_;
  168. while (freeQueue.length) {
  169. this.disposeObject(freeQueue.pop());
  170. }
  171. delete this.freeQueue_;
  172. };