1 /* Licensed to the Apache Software Foundation (ASF) under one or more
  2  * contributor license agreements.  See the NOTICE file distributed with
  3  * this work for additional information regarding copyright ownership.
  4  * The ASF licenses this file to you under the Apache License, Version 2.0
  5  * (the "License"); you may not use this file except in compliance with
  6  * the License.  You may obtain a copy of the License at
  7  *
  8  *      http://www.apache.org/licenses/LICENSE-2.0
  9  *
 10  * Unless required by applicable law or agreed to in writing, software
 11  * distributed under the License is distributed on an "AS IS" BASIS,
 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  * See the License for the specific language governing permissions and
 14  * limitations under the License.
 15  */
 16 
 17 /**
 18  * @class
 19  * @name _Queue
 20  * @memberOf myfaces._impl._util
 21  * @description Queue implementation used by our runtime system
 22  * improved version of
 23  * @see <a href="http://safalra.com/web-design/javascript/queues/Queue.js">http://safalra.com/web-design/javascript/queues/Queue.js</a>
 24  */
 25 myfaces._impl.core._Runtime.extendClass("myfaces._impl._util._Queue", Object,
 26   /**
 27    * @lends myfaces._impl._util._Queue.prototype
 28    */
 29 {
 30     //faster queue by http://safalra.com/web-design/javascript/queues/Queue.js
 31     //license public domain
 32     //The trick is to simply reduce the number of slice and slice ops to a bare minimum.
 33 
 34     _q : null,
 35     _space : 0,
 36     _size: -1,
 37 
 38     /**
 39      * Standard constructor
 40      */
 41     constructor_: function() {
 42         this._q = [];
 43         this._Lang = myfaces._impl._util._Lang;
 44     },
 45 
 46     /**
 47      * @return the length of the queue as integer
 48      */
 49     length: function() {
 50         // return the number of elements in the queue
 51         return this._q.length - this._space;
 52 
 53     },
 54 
 55     /**
 56      * @return true if the current queue is empty false otherwise
 57      */
 58     isEmpty: function() {
 59         // return true if the queue is empty, and false otherwise
 60         return (this._q.length == 0);
 61     },
 62 
 63     /**
 64      * Sets the current queue to a new size, all overflow elements at the end are stripped
 65      * automatically
 66      *
 67      * @param {int} newSize as numeric value
 68      */
 69     setQueueSize: function(newSize) {
 70         this._size = newSize;
 71         this._readjust();
 72     },
 73 
 74     /**
 75      * adds a listener to the queue
 76      *
 77      * @param element the listener to be added
 78      */
 79     enqueue : function(/*function*/element) {
 80         this._q.push(element);
 81         //qeuesize is bigger than the limit we drop one element so that we are
 82         //back in line
 83 
 84         this._readjust();
 85     },
 86 
 87     _readjust: function() {
 88         var size = this._size;
 89         while (null != size && 'undefined' != typeof size &&
 90                 size > -1 && this.length() > size) {
 91             this.dequeue();
 92         }
 93     },
 94 
 95     /**
 96      * removes a listener form the queue
 97      *
 98      * @param element the listener to be removed
 99      */
100     remove : function(/*function*/element) {
101         /*find element in queue*/
102         var index = this.indexOf(element);
103         /*found*/
104         if (index != -1) {
105             this._q.splice(index, 1);
106         }
107     },
108 
109     /**
110      * dequeues the last element in the queue
111      * @return {Object} element which is dequeued
112      */
113     dequeue: function() {
114         // initialise the element to return to be undefined
115         var element = null;
116 
117         // check whether the queue is empty
118         var qLen = this._q.length;
119         var queue = this._q;
120         
121         if (qLen) {
122 
123             // fetch the oldest element in the queue
124             element = queue[this._space];
125 
126             // update the amount of space and check whether a shift should occur
127             //added here a max limit of 30
128             //now bit shift left is a tad faster than multiplication on most vms and does the same
129             //unless we run into a bit skipping which is impossible in our usecases here
130             if ((++this._space) << 1 >= qLen) {
131 
132                 // set the queue equal to the non-empty portion of the queue
133                 this._q = queue.slice(this._space);
134 
135                 // reset the amount of space at the front of the queue
136                 this._space = 0;
137 
138             }
139 
140         }
141 
142         // return the removed element
143         return element;
144     },
145 
146     /**
147      * simple foreach
148      *
149      * @param closure a closure which processes the element
150      * @code
151      *   queue.each(function(element) {
152      *      //do something with the element
153      *   });
154      */
155     each: function(closure) {
156         this._Lang.arrForEach(this._q, closure, this._space);
157     },
158 
159     /**
160      * Simple filter
161      *
162      * @param closure a closure which returns true or false depending
163      * whether the filter has triggered
164      *
165      * @return an array of filtered queue entries
166      */
167     arrFilter: function(closure) {
168         return this._Lang.arrFilter(this._q, closure, this._space);
169     },
170 
171     /**
172      * @param element
173      * @return the current index of the element in the queue or -1 if it is not found
174      */
175     indexOf: function(element) {
176         return this._Lang.arrIndexOf(this._q, element);
177     },
178 
179     /**
180      * resets the queue to initial empty state
181      */
182     cleanup: function() {
183         this._q = [];
184         this._space = 0;
185     }
186 });
187 
188