|
activemq-cpp-3.4.0
|
00001 /* 00002 * Licensed to the Apache Software Foundation (ASF) under one or more 00003 * contributor license agreements. See the NOTICE file distributed with 00004 * this work for additional information regarding copyright ownership. 00005 * The ASF licenses this file to You under the Apache License, Version 2.0 00006 * (the "License"); you may not use this file except in compliance with 00007 * the License. You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef _DECAF_UTIL_PRIORITYQUEUE_H_ 00019 #define _DECAF_UTIL_PRIORITYQUEUE_H_ 00020 00021 #include <decaf/util/Config.h> 00022 #include <decaf/util/Collection.h> 00023 #include <decaf/util/AbstractQueue.h> 00024 #include <decaf/util/Iterator.h> 00025 #include <decaf/util/Comparator.h> 00026 #include <decaf/util/comparators/Less.h> 00027 00028 #include <decaf/lang/Math.h> 00029 #include <decaf/lang/Pointer.h> 00030 #include <decaf/lang/exceptions/NullPointerException.h> 00031 #include <decaf/lang/exceptions/UnsupportedOperationException.h> 00032 00033 #include <memory> 00034 00035 namespace decaf { 00036 namespace util { 00037 00068 template< typename E > 00069 class PriorityQueue : public AbstractQueue<E> { 00070 private: 00071 00072 static const int DEFAULT_CAPACITY = 11; 00073 static const int DEFAULT_CAPACITY_RATIO = 2; 00074 00075 int _size; 00076 int capacity; 00077 E* elements; 00078 decaf::lang::Pointer< Comparator<E> > _comparator; 00079 00080 private: 00081 00082 class PriorityQueueIterator : public Iterator<E> { 00083 private: 00084 00085 PriorityQueueIterator( const PriorityQueueIterator& ); 00086 PriorityQueueIterator& operator= ( const PriorityQueueIterator& ); 00087 00088 private: 00089 00090 int position; 00091 bool allowRemove; 00092 PriorityQueue* queue; 00093 00094 public: 00095 00096 PriorityQueueIterator( PriorityQueue* queue ) : position( 0 ), allowRemove( false ), queue( queue ) {} 00097 00098 virtual E next() { 00099 00100 if( !hasNext() ) { 00101 throw NoSuchElementException( 00102 __FILE__, __LINE__, 00103 "No more elements to Iterate over." ); 00104 } 00105 00106 allowRemove = true; 00107 return queue->elements[position++]; 00108 } 00109 00110 virtual bool hasNext() const { 00111 return position < queue->_size; 00112 } 00113 00114 virtual void remove() { 00115 00116 if( !allowRemove ) { 00117 throw lang::exceptions::IllegalStateException( 00118 __FILE__, __LINE__, 00119 "No more elements to Iterate over." ); 00120 } 00121 00122 allowRemove = false; 00123 queue->removeAt( position-- ); 00124 } 00125 }; 00126 00127 class ConstPriorityQueueIterator : public PriorityQueueIterator { 00128 private: 00129 00130 ConstPriorityQueueIterator( const ConstPriorityQueueIterator& ); 00131 ConstPriorityQueueIterator& operator= ( const ConstPriorityQueueIterator& ); 00132 00133 public: 00134 00135 ConstPriorityQueueIterator( const PriorityQueue* queue ) : 00136 PriorityQueueIterator( const_cast<PriorityQueue*>( queue ) ) {} 00137 00138 virtual void remove() { 00139 throw lang::exceptions::UnsupportedOperationException( 00140 __FILE__, __LINE__, 00141 "PriorityQueue::Iterator::remove - Not Valid on a Const Iterator" ); 00142 } 00143 }; 00144 00145 friend class PriorityQueueIterator; 00146 00147 public: 00148 00152 PriorityQueue() : AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() { 00153 this->initQueue( DEFAULT_CAPACITY, new comparators::Less<E>() ); 00154 } 00155 00162 PriorityQueue( int initialCapacity ) : 00163 AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() { 00164 00165 this->initQueue( initialCapacity, new comparators::Less<E>() ); 00166 } 00167 00180 PriorityQueue( int initialCapacity, Comparator<E>* comparator ) : 00181 AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() { 00182 00183 if( comparator == NULL ) { 00184 throw decaf::lang::exceptions::NullPointerException( 00185 __FILE__, __LINE__, "Passed Comparator Cannot be NULL." ); 00186 } 00187 00188 this->initQueue( initialCapacity, comparator ); 00189 } 00190 00197 PriorityQueue( const Collection<E>& source ) : 00198 AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() { 00199 00200 this->getFromCollection( source ); 00201 } 00202 00210 PriorityQueue( const PriorityQueue<E>& source ) : 00211 AbstractQueue<E>(), _size( 0 ), capacity( 0 ), elements( NULL ), _comparator() { 00212 00213 this->getFromPriorityQueue( source ); 00214 } 00215 00216 virtual ~PriorityQueue() { 00217 delete [] elements; 00218 } 00219 00226 PriorityQueue<E>& operator= ( const Collection<E>& source ) { 00227 this->getFromCollection( source ); 00228 } 00229 00236 PriorityQueue<E>& operator= ( const PriorityQueue<E>& source ) { 00237 this->getFromPriorityQueue( source ); 00238 } 00239 00240 public: 00241 00242 virtual decaf::util::Iterator<E>* iterator() { 00243 return new PriorityQueueIterator( this ); 00244 } 00245 00246 virtual decaf::util::Iterator<E>* iterator() const { 00247 return new ConstPriorityQueueIterator( this ); 00248 } 00249 00250 virtual int size() const { 00251 return this->_size; 00252 } 00253 00254 virtual void clear() { 00255 00256 // TODO - Provide a more efficient way to clear the array without reallocating it 00257 // we should keep the size it grew to since if reused it could get that big 00258 // again and reallocating all that memory could be to slow. 00259 00260 delete [] this->elements; 00261 00262 this->elements = new E[DEFAULT_CAPACITY]; 00263 this->capacity = DEFAULT_CAPACITY; 00264 this->_size = 0; 00265 } 00266 00267 virtual bool offer( const E& value ) { 00268 00269 // TODO - Check for Null and throw exception 00270 00271 increaseCapacity( _size + 1 ); 00272 elements[_size++] = value; 00273 upHeap(); 00274 return true; 00275 } 00276 00277 virtual bool poll( E& result ) { 00278 00279 if( this->isEmpty() ) { 00280 return false; 00281 } 00282 00283 result = elements[0]; 00284 removeAt( 0 ); 00285 return true; 00286 } 00287 00288 virtual bool peek( E& result ) const { 00289 00290 if( this->isEmpty() ) { 00291 return false; 00292 } 00293 00294 result = elements[0]; 00295 return true; 00296 } 00297 00298 virtual E remove() { 00299 00300 if( !this->isEmpty() ) { 00301 E result = elements[0]; 00302 removeAt( 0 ); 00303 return result; 00304 } 00305 00306 throw decaf::util::NoSuchElementException( 00307 __FILE__, __LINE__, "Unable to remove specified element from the Queue." ); 00308 } 00309 00310 virtual bool remove( const E& value ) { 00311 00312 int targetIndex = 0; 00313 for( targetIndex = 0; targetIndex < _size; targetIndex++ ) { 00314 if( 0 == _comparator->compare( value, elements[targetIndex] ) ) { 00315 break; 00316 } 00317 } 00318 00319 if( _size == 0 || _size == targetIndex ) { 00320 return false; 00321 } 00322 00323 removeAt( targetIndex ); 00324 return true; 00325 } 00326 00327 virtual bool add( const E& value ) { 00328 00329 try { 00330 return offer( value ); 00331 } 00332 DECAF_CATCH_RETHROW( lang::exceptions::UnsupportedOperationException ) 00333 DECAF_CATCH_RETHROW( lang::exceptions::IllegalArgumentException ) 00334 DECAF_CATCH_RETHROW( lang::exceptions::IllegalStateException ) 00335 DECAF_CATCH_EXCEPTION_CONVERT( lang::exceptions::NullPointerException, lang::exceptions::UnsupportedOperationException ) 00336 DECAF_CATCHALL_THROW( lang::exceptions::UnsupportedOperationException ) 00337 } 00338 00346 decaf::lang::Pointer< Comparator<E> > comparator() const { 00347 return this->_comparator; 00348 } 00349 00350 private: 00351 00352 void initQueue( int initialSize, Comparator<E>* comparator ) { 00353 this->elements = new E[initialSize]; 00354 this->capacity = initialSize; 00355 this->_size = 0; 00356 this->_comparator.reset( comparator ); 00357 } 00358 00359 void upHeap() { 00360 00361 int current = _size - 1; 00362 int parent = ( current - 1 ) / 2; 00363 00364 while( current != 0 && _comparator->compare( elements[current], elements[parent] ) < 0 ) { 00365 00366 // swap the two 00367 E tmp = elements[current]; 00368 elements[current] = elements[parent]; 00369 elements[parent] = tmp; 00370 00371 // update parent and current positions. 00372 current = parent; 00373 parent = ( current - 1 ) / 2; 00374 } 00375 } 00376 00377 void downHeap( int pos ) { 00378 00379 int current = pos; 00380 int child = 2 * current + 1; 00381 00382 while( child < _size && !this->isEmpty() ) { 00383 00384 // compare the children if they exist 00385 if( child + 1 < _size && _comparator->compare( elements[child + 1], elements[child] ) < 0 ) { 00386 child++; 00387 } 00388 00389 // compare selected child with parent 00390 if( _comparator->compare( elements[current], elements[child] ) < 0 ) { 00391 break; 00392 } 00393 00394 // swap the two 00395 E tmp = elements[current]; 00396 elements[current] = elements[child]; 00397 elements[child] = tmp; 00398 00399 // update child and current positions 00400 current = child; 00401 child = 2 * current + 1; 00402 } 00403 } 00404 00405 void getFromPriorityQueue( const PriorityQueue<E>& c ) { 00406 initCapacity( c ); 00407 _comparator = c.comparator(); 00408 for( int ix = 0; ix < c.size(); ++ix ) { 00409 this->elements[ix] = c.elements[ix]; 00410 } 00411 _size = c.size(); 00412 } 00413 00414 void getFromCollection( const Collection<E>& c ) { 00415 initCapacity( c ); 00416 _comparator.reset( new comparators::Less<E>() ); 00417 std::auto_ptr< Iterator<E> > iter( c.iterator() ); 00418 while( iter->hasNext() ) { 00419 this->offer( iter->next() ); 00420 } 00421 } 00422 00423 void removeAt( int index ) { 00424 _size--; 00425 elements[index] = elements[_size]; 00426 downHeap(index); 00427 elements[_size] = E(); 00428 } 00429 00430 void initCapacity( const Collection<E>& c ) { 00431 00432 delete [] elements; 00433 _size = 0; 00434 00435 if( c.isEmpty() ) { 00436 capacity = 1; 00437 elements = new E[capacity]; 00438 } else { 00439 capacity = (int) lang::Math::ceil( (double)c.size() * 1.1 ); 00440 elements = new E[capacity]; 00441 } 00442 } 00443 00444 void increaseCapacity( int size ) { 00445 00446 if( size > capacity ) { 00447 E* newElements = new E[ size * DEFAULT_CAPACITY_RATIO ]; 00448 00449 for( int ix = 0; ix < capacity; ix++ ) { 00450 newElements[ix] = elements[ix]; 00451 } 00452 00453 delete [] elements; 00454 00455 elements = newElements; 00456 capacity = size * DEFAULT_CAPACITY_RATIO; 00457 } 00458 } 00459 00460 }; 00461 00462 }} 00463 00464 #endif /* _DECAF_UTIL_PRIORITYQUEUE_H_ */