123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- // Copyright 2015 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.
- goog.provide('goog.async.WorkItem');
- goog.provide('goog.async.WorkQueue');
- goog.require('goog.asserts');
- goog.require('goog.async.FreeList');
- // TODO(johnlenz): generalize the WorkQueue if this is used by more
- // than goog.async.run.
- /**
- * A low GC workqueue. The key elements of this design:
- * - avoids the need for goog.bind or equivalent by carrying scope
- * - avoids the need for array reallocation by using a linked list
- * - minimizes work entry objects allocation by recycling objects
- * @constructor
- * @final
- * @struct
- */
- goog.async.WorkQueue = function() {
- this.workHead_ = null;
- this.workTail_ = null;
- };
- /** @define {number} The maximum number of entries to keep for recycling. */
- goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);
- /** @const @private {goog.async.FreeList<goog.async.WorkItem>} */
- goog.async.WorkQueue.freelist_ = new goog.async.FreeList(
- function() { return new goog.async.WorkItem(); },
- function(item) { item.reset(); }, goog.async.WorkQueue.DEFAULT_MAX_UNUSED);
- /**
- * @param {function()} fn
- * @param {Object|null|undefined} scope
- */
- goog.async.WorkQueue.prototype.add = function(fn, scope) {
- var item = this.getUnusedItem_();
- item.set(fn, scope);
- if (this.workTail_) {
- this.workTail_.next = item;
- this.workTail_ = item;
- } else {
- goog.asserts.assert(!this.workHead_);
- this.workHead_ = item;
- this.workTail_ = item;
- }
- };
- /**
- * @return {goog.async.WorkItem}
- */
- goog.async.WorkQueue.prototype.remove = function() {
- var item = null;
- if (this.workHead_) {
- item = this.workHead_;
- this.workHead_ = this.workHead_.next;
- if (!this.workHead_) {
- this.workTail_ = null;
- }
- item.next = null;
- }
- return item;
- };
- /**
- * @param {goog.async.WorkItem} item
- */
- goog.async.WorkQueue.prototype.returnUnused = function(item) {
- goog.async.WorkQueue.freelist_.put(item);
- };
- /**
- * @return {goog.async.WorkItem}
- * @private
- */
- goog.async.WorkQueue.prototype.getUnusedItem_ = function() {
- return goog.async.WorkQueue.freelist_.get();
- };
- /**
- * @constructor
- * @final
- * @struct
- */
- goog.async.WorkItem = function() {
- /** @type {?function()} */
- this.fn = null;
- /** @type {Object|null|undefined} */
- this.scope = null;
- /** @type {?goog.async.WorkItem} */
- this.next = null;
- };
- /**
- * @param {function()} fn
- * @param {Object|null|undefined} scope
- */
- goog.async.WorkItem.prototype.set = function(fn, scope) {
- this.fn = fn;
- this.scope = scope;
- this.next = null;
- };
- /** Reset the work item so they don't prevent GC before reuse */
- goog.async.WorkItem.prototype.reset = function() {
- this.fn = null;
- this.scope = null;
- this.next = null;
- };
|