00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef __QUEUE_H
00011 #define __QUEUE_H
00012
00013
00014 #include "RakAssert.h"
00015 #include "Export.h"
00016 #include "RakMemoryOverride.h"
00017
00020 namespace DataStructures
00021 {
00023 template <class queue_type>
00024 class RAK_DLL_EXPORT Queue
00025 {
00026 public:
00027 Queue();
00028 ~Queue();
00029 Queue( Queue& original_copy );
00030 bool operator= ( const Queue& original_copy );
00031 void Push( const queue_type& input, const char *file, unsigned int line );
00032 void PushAtHead( const queue_type& input, unsigned index, const char *file, unsigned int line );
00033 queue_type& operator[] ( unsigned int position ) const;
00034 void RemoveAtIndex( unsigned int position );
00035 inline queue_type Peek( void ) const;
00036 inline queue_type PeekTail( void ) const;
00037 inline queue_type Pop( void );
00038
00039 inline queue_type PopDeref( void );
00040 inline unsigned int Size( void ) const;
00041 inline bool IsEmpty(void) const;
00042 inline unsigned int AllocationSize( void ) const;
00043 inline void Clear( const char *file, unsigned int line );
00044 void Compress( const char *file, unsigned int line );
00045 bool Find ( queue_type q );
00046 void ClearAndForceAllocation( int size, const char *file, unsigned int line );
00047
00048 private:
00049 queue_type* array;
00050 unsigned int head;
00051 unsigned int tail;
00052 unsigned int allocation_size;
00053 };
00054
00055
00056 template <class queue_type>
00057 inline unsigned int Queue<queue_type>::Size( void ) const
00058 {
00059 if ( head <= tail )
00060 return tail -head;
00061 else
00062 return allocation_size -head + tail;
00063 }
00064
00065 template <class queue_type>
00066 inline bool Queue<queue_type>::IsEmpty(void) const
00067 {
00068 return head==tail;
00069 }
00070
00071 template <class queue_type>
00072 inline unsigned int Queue<queue_type>::AllocationSize( void ) const
00073 {
00074 return allocation_size;
00075 }
00076
00077 template <class queue_type>
00078 Queue<queue_type>::Queue()
00079 {
00080
00081
00082 allocation_size = 0;
00083 array=0;
00084 head = 0;
00085 tail = 0;
00086 }
00087
00088 template <class queue_type>
00089 Queue<queue_type>::~Queue()
00090 {
00091 if (allocation_size>0)
00092 RakNet::OP_DELETE_ARRAY(array, __FILE__, __LINE__);
00093 }
00094
00095 template <class queue_type>
00096 inline queue_type Queue<queue_type>::Pop( void )
00097 {
00098 #ifdef _DEBUG
00099 RakAssert( head != tail);
00100 #endif
00101
00102
00103 if ( ++head == allocation_size )
00104 head = 0;
00105
00106 if ( head == 0 )
00107 return ( queue_type ) array[ allocation_size -1 ];
00108
00109 return ( queue_type ) array[ head -1 ];
00110 }
00111
00112 template <class queue_type>
00113 inline queue_type Queue<queue_type>::PopDeref( void )
00114 {
00115 if ( ++head == allocation_size )
00116 head = 0;
00117
00118 queue_type q;
00119 if ( head == 0 )
00120 {
00121 q=array[ allocation_size -1 ];
00122 array[ allocation_size -1 ]=0;
00123 return q;
00124 }
00125
00126 q=array[ head -1 ];
00127 array[ head -1 ]=0;
00128 return q;
00129 }
00130
00131 template <class queue_type>
00132 void Queue<queue_type>::PushAtHead( const queue_type& input, unsigned index, const char *file, unsigned int line )
00133 {
00134 RakAssert(index <= Size());
00135
00136
00137 Push(input, file, line );
00138
00139 if (Size()==1)
00140 return;
00141
00142 unsigned writeIndex, readIndex, trueWriteIndex, trueReadIndex;
00143 writeIndex=Size()-1;
00144 readIndex=writeIndex-1;
00145 while (readIndex >= index)
00146 {
00147 if ( head + writeIndex >= allocation_size )
00148 trueWriteIndex = head + writeIndex - allocation_size;
00149 else
00150 trueWriteIndex = head + writeIndex;
00151
00152 if ( head + readIndex >= allocation_size )
00153 trueReadIndex = head + readIndex - allocation_size;
00154 else
00155 trueReadIndex = head + readIndex;
00156
00157 array[trueWriteIndex]=array[trueReadIndex];
00158
00159 if (readIndex==0)
00160 break;
00161 writeIndex--;
00162 readIndex--;
00163 }
00164
00165 if ( head + index >= allocation_size )
00166 trueWriteIndex = head + index - allocation_size;
00167 else
00168 trueWriteIndex = head + index;
00169
00170 array[trueWriteIndex]=input;
00171 }
00172
00173
00174 template <class queue_type>
00175 inline queue_type Queue<queue_type>::Peek( void ) const
00176 {
00177 #ifdef _DEBUG
00178 RakAssert( head != tail );
00179 #endif
00180
00181 return ( queue_type ) array[ head ];
00182 }
00183
00184 template <class queue_type>
00185 inline queue_type Queue<queue_type>::PeekTail( void ) const
00186 {
00187 #ifdef _DEBUG
00188 RakAssert( head != tail );
00189 #endif
00190 if (tail!=0)
00191 return ( queue_type ) array[ tail-1 ];
00192 else
00193 return ( queue_type ) array[ allocation_size-1 ];
00194 }
00195
00196 template <class queue_type>
00197 void Queue<queue_type>::Push( const queue_type& input, const char *file, unsigned int line )
00198 {
00199 if ( allocation_size == 0 )
00200 {
00201 array = RakNet::OP_NEW_ARRAY<queue_type>(16, file, line );
00202 head = 0;
00203 tail = 1;
00204 array[ 0 ] = input;
00205 allocation_size = 16;
00206 return ;
00207 }
00208
00209 array[ tail++ ] = input;
00210
00211 if ( tail == allocation_size )
00212 tail = 0;
00213
00214 if ( tail == head )
00215 {
00216
00217
00218
00219 queue_type * new_array;
00220 new_array = RakNet::OP_NEW_ARRAY<queue_type>(allocation_size * 2, file, line );
00221 #ifdef _DEBUG
00222 RakAssert( new_array );
00223 #endif
00224 if (new_array==0)
00225 return;
00226
00227 for ( unsigned int counter = 0; counter < allocation_size; ++counter )
00228 new_array[ counter ] = array[ ( head + counter ) % ( allocation_size ) ];
00229
00230 head = 0;
00231
00232 tail = allocation_size;
00233
00234 allocation_size *= 2;
00235
00236
00237 RakNet::OP_DELETE_ARRAY(array, file, line);
00238
00239 array = new_array;
00240 }
00241
00242 }
00243
00244 template <class queue_type>
00245 Queue<queue_type>::Queue( Queue& original_copy )
00246 {
00247
00248
00249 if ( original_copy.Size() == 0 )
00250 {
00251 allocation_size = 0;
00252 }
00253
00254 else
00255 {
00256 array = RakNet::OP_NEW_ARRAY<queue_type >( original_copy.Size() + 1 , __FILE__, __LINE__ );
00257
00258 for ( unsigned int counter = 0; counter < original_copy.Size(); ++counter )
00259 array[ counter ] = original_copy.array[ ( original_copy.head + counter ) % ( original_copy.allocation_size ) ];
00260
00261 head = 0;
00262
00263 tail = original_copy.Size();
00264
00265 allocation_size = original_copy.Size() + 1;
00266 }
00267 }
00268
00269 template <class queue_type>
00270 bool Queue<queue_type>::operator= ( const Queue& original_copy )
00271 {
00272 if ( ( &original_copy ) == this )
00273 return false;
00274
00275 Clear(__FILE__, __LINE__);
00276
00277
00278 if ( original_copy.Size() == 0 )
00279 {
00280 allocation_size = 0;
00281 }
00282
00283 else
00284 {
00285 array = RakNet::OP_NEW_ARRAY<queue_type >( original_copy.Size() + 1 , __FILE__, __LINE__ );
00286
00287 for ( unsigned int counter = 0; counter < original_copy.Size(); ++counter )
00288 array[ counter ] = original_copy.array[ ( original_copy.head + counter ) % ( original_copy.allocation_size ) ];
00289
00290 head = 0;
00291
00292 tail = original_copy.Size();
00293
00294 allocation_size = original_copy.Size() + 1;
00295 }
00296
00297 return true;
00298 }
00299
00300 template <class queue_type>
00301 inline void Queue<queue_type>::Clear ( const char *file, unsigned int line )
00302 {
00303 if ( allocation_size == 0 )
00304 return ;
00305
00306 if (allocation_size > 32)
00307 {
00308 RakNet::OP_DELETE_ARRAY(array, file, line);
00309 allocation_size = 0;
00310 }
00311
00312 head = 0;
00313 tail = 0;
00314 }
00315
00316 template <class queue_type>
00317 void Queue<queue_type>::Compress ( const char *file, unsigned int line )
00318 {
00319 queue_type* new_array;
00320 unsigned int newAllocationSize;
00321 if (allocation_size==0)
00322 return;
00323
00324 newAllocationSize=1;
00325 while (newAllocationSize <= Size())
00326 newAllocationSize<<=1;
00327
00328 new_array = RakNet::OP_NEW_ARRAY<queue_type >(newAllocationSize, file, line );
00329
00330 for (unsigned int counter=0; counter < Size(); ++counter)
00331 new_array[counter] = array[(head + counter)%(allocation_size)];
00332
00333 tail=Size();
00334 allocation_size=newAllocationSize;
00335 head=0;
00336
00337
00338 RakNet::OP_DELETE_ARRAY(array, file, line);
00339 array=new_array;
00340 }
00341
00342 template <class queue_type>
00343 bool Queue<queue_type>::Find ( queue_type q )
00344 {
00345 if ( allocation_size == 0 )
00346 return false;
00347
00348 unsigned int counter = head;
00349
00350 while ( counter != tail )
00351 {
00352 if ( array[ counter ] == q )
00353 return true;
00354
00355 counter = ( counter + 1 ) % allocation_size;
00356 }
00357
00358 return false;
00359 }
00360
00361 template <class queue_type>
00362 void Queue<queue_type>::ClearAndForceAllocation( int size, const char *file, unsigned int line )
00363 {
00364 RakNet::OP_DELETE_ARRAY(array, file, line);
00365 array = RakNet::OP_NEW_ARRAY<queue_type>(size, file, line );
00366 allocation_size = size;
00367 head = 0;
00368 tail = 0;
00369 }
00370
00371 template <class queue_type>
00372 inline queue_type& Queue<queue_type>::operator[] ( unsigned int position ) const
00373 {
00374 #ifdef _DEBUG
00375 RakAssert( position < Size() );
00376 #endif
00377
00378
00379 if ( head + position >= allocation_size )
00380 return array[ head + position - allocation_size ];
00381 else
00382 return array[ head + position ];
00383 }
00384
00385 template <class queue_type>
00386 void Queue<queue_type>::RemoveAtIndex( unsigned int position )
00387 {
00388 #ifdef _DEBUG
00389 RakAssert( position < Size() );
00390 RakAssert( head != tail );
00391 #endif
00392
00393 if ( head == tail || position >= Size() )
00394 return ;
00395
00396 unsigned int index;
00397
00398 unsigned int next;
00399
00400
00401 if ( head + position >= allocation_size )
00402 index = head + position - allocation_size;
00403 else
00404 index = head + position;
00405
00406
00407 next = index + 1;
00408
00409 if ( next == allocation_size )
00410 next = 0;
00411
00412 while ( next != tail )
00413 {
00414
00415 array[ index ] = array[ next ];
00416 index = next;
00417
00418
00419 if ( ++next == allocation_size )
00420 next = 0;
00421 }
00422
00423
00424 if ( tail == 0 )
00425 tail = allocation_size - 1;
00426 else
00427 --tail;
00428 }
00429 }
00430
00431 #endif
00432