Path: blob/trunk/third_party/closure/goog/async/workqueue.js
2868 views
// Copyright 2015 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314goog.provide('goog.async.WorkItem');15goog.provide('goog.async.WorkQueue');1617goog.require('goog.asserts');18goog.require('goog.async.FreeList');192021// TODO(johnlenz): generalize the WorkQueue if this is used by more22// than goog.async.run.23242526/**27* A low GC workqueue. The key elements of this design:28* - avoids the need for goog.bind or equivalent by carrying scope29* - avoids the need for array reallocation by using a linked list30* - minimizes work entry objects allocation by recycling objects31* @constructor32* @final33* @struct34*/35goog.async.WorkQueue = function() {36this.workHead_ = null;37this.workTail_ = null;38};394041/** @define {number} The maximum number of entries to keep for recycling. */42goog.define('goog.async.WorkQueue.DEFAULT_MAX_UNUSED', 100);434445/** @const @private {goog.async.FreeList<goog.async.WorkItem>} */46goog.async.WorkQueue.freelist_ = new goog.async.FreeList(47function() { return new goog.async.WorkItem(); },48function(item) { item.reset(); }, goog.async.WorkQueue.DEFAULT_MAX_UNUSED);495051/**52* @param {function()} fn53* @param {Object|null|undefined} scope54*/55goog.async.WorkQueue.prototype.add = function(fn, scope) {56var item = this.getUnusedItem_();57item.set(fn, scope);5859if (this.workTail_) {60this.workTail_.next = item;61this.workTail_ = item;62} else {63goog.asserts.assert(!this.workHead_);64this.workHead_ = item;65this.workTail_ = item;66}67};686970/**71* @return {goog.async.WorkItem}72*/73goog.async.WorkQueue.prototype.remove = function() {74var item = null;7576if (this.workHead_) {77item = this.workHead_;78this.workHead_ = this.workHead_.next;79if (!this.workHead_) {80this.workTail_ = null;81}82item.next = null;83}84return item;85};868788/**89* @param {goog.async.WorkItem} item90*/91goog.async.WorkQueue.prototype.returnUnused = function(item) {92goog.async.WorkQueue.freelist_.put(item);93};949596/**97* @return {goog.async.WorkItem}98* @private99*/100goog.async.WorkQueue.prototype.getUnusedItem_ = function() {101return goog.async.WorkQueue.freelist_.get();102};103104105106/**107* @constructor108* @final109* @struct110*/111goog.async.WorkItem = function() {112/** @type {?function()} */113this.fn = null;114/** @type {Object|null|undefined} */115this.scope = null;116/** @type {?goog.async.WorkItem} */117this.next = null;118};119120121/**122* @param {function()} fn123* @param {Object|null|undefined} scope124*/125goog.async.WorkItem.prototype.set = function(fn, scope) {126this.fn = fn;127this.scope = scope;128this.next = null;129};130131132/** Reset the work item so they don't prevent GC before reuse */133goog.async.WorkItem.prototype.reset = function() {134this.fn = null;135this.scope = null;136this.next = null;137};138139140