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 _MF_CLS(_PFX_UTIL+"_Queue", _MF_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._callSuper("constructor_");
 43         this._q = [];
 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 (size && size > -1 && this.length() > size) {
 90             this.dequeue();
 91         }
 92     },
 93 
 94     /**
 95      * removes a listener form the queue
 96      *
 97      * @param element the listener to be removed
 98      */
 99     remove : function(/*function*/element) {
100         /*find element in queue*/
101         var index = this.indexOf(element);
102         /*found*/
103         if (index != -1) {
104             this._q.splice(index, 1);
105         }
106     },
107 
108     /**
109      * dequeues the last element in the queue
110      * @return {Object} element which is dequeued
111      */
112     dequeue: function() {
113         // initialise the element to return to be undefined
114         var element = null;
115 
116         // check whether the queue is empty
117         var qLen = this._q.length;
118         var queue = this._q;
119         
120         if (qLen) {
121 
122             // fetch the oldest element in the queue
123             element = queue[this._space];
124 
125             // update the amount of space and check whether a shift should occur
126             //added here a max limit of 30
127             //now bit shift left is a tad faster than multiplication on most vms and does the same
128             //unless we run into a bit skipping which is impossible in our usecases here
129             if ((++this._space) << 1 >= qLen) {
130 
131                 // set the queue equal to the non-empty portion of the queue
132                 this._q = queue.slice(this._space);
133 
134                 // reset the amount of space at the front of the queue
135                 this._space = 0;
136 
137             }
138 
139         }
140 
141         // return the removed element
142         return element;
143     },
144 
145     /**
146      * simple foreach
147      *
148      * @param closure a closure which processes the element
149      * @code
150      *   queue.each(function(element) {
151      *      //do something with the element
152      *   });
153      */
154     each: function(closure) {
155         this._Lang.arrForEach(this._q, closure, this._space);
156     },
157 
158     /**
159      * Simple filter
160      *
161      * @param closure a closure which returns true or false depending
162      * whether the filter has triggered
163      *
164      * @return an array of filtered queue entries
165      */
166     arrFilter: function(closure) {
167         return this._Lang.arrFilter(this._q, closure, this._space);
168     },
169 
170     /**
171      * @param element
172      * @return the current index of the element in the queue or -1 if it is not found
173      */
174     indexOf: function(element) {
175         return this._Lang.arrIndexOf(this._q, element);
176     },
177 
178     /**
179      * resets the queue to initial empty state
180      */
181     cleanup: function() {
182         this._q = [];
183         this._space = 0;
184     }
185 });
186 
187