SLikeNet 0.1.3

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DS_Queue.h
Go to the documentation of this file.
1 /*
2 * Original work: Copyright (c) 2014, Oculus VR, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under the BSD-style license found in the
6 * RakNet License.txt file in the licenses directory of this source tree. An additional grant
7 * of patent rights can be found in the RakNet Patents.txt file in the same directory.
8 *
9 *
10 * Modified work: Copyright (c) 2016-2017, SLikeSoft UG (haftungsbeschränkt)
11 *
12 * This source code was modified by SLikeSoft. Modifications are licensed under the MIT-style
13 * license found in the license.txt file in the root directory of this source tree.
14 */
15
20
21
22 #ifndef __QUEUE_H
23 #define __QUEUE_H
24
25 // Template classes have to have all the code in the header file
26 #include "assert.h"
27 #include "Export.h"
28 #include "memoryoverride.h"
29
32 namespace DataStructures
33 {
35 template <class queue_type>
36 class RAK_DLL_EXPORT Queue
37 {
38 public:
39 Queue();
40 ~Queue();
41 Queue( const Queue& original_copy );
42 bool operator= ( const Queue& original_copy );
43 void Push( const queue_type& input, const char *file, unsigned int line );
44 void PushAtHead( const queue_type& input, unsigned index, const char *file, unsigned int line );
45 queue_type& operator[] ( unsigned int position ) const; // Not a normal thing you do with a queue but can be used for efficiency
46 void RemoveAtIndex( unsigned int position ); // Not a normal thing you do with a queue but can be used for efficiency
47 inline queue_type Peek( void ) const;
48 inline queue_type PeekTail( void ) const;
49 inline queue_type Pop( void );
50 inline queue_type PopTail( void );
51 // Debug: Set pointer to 0, for memory leak detection
52 inline queue_type PopDeref( void );
53 inline unsigned int Size( void ) const;
54 inline bool IsEmpty(void) const;
55 inline unsigned int AllocationSize( void ) const;
56 inline void Clear( const char *file, unsigned int line );
57 void Compress( const char *file, unsigned int line );
58 bool Find ( const queue_type& q );
59 void ClearAndForceAllocation( int size, const char *file, unsigned int line ); // Force a memory allocation to a certain larger size
60
61 private:
62 queue_type* array;
63 unsigned int head; // Array index for the head of the queue
64 unsigned int tail; // Array index for the tail of the queue
65 unsigned int allocation_size;
66 };
67
68
69 template <class queue_type>
70 inline unsigned int Queue<queue_type>::Size( void ) const
71 {
72 if ( head <= tail )
73 return tail -head;
74 else
75 return allocation_size -head + tail;
76 }
77
78 template <class queue_type>
79 inline bool Queue<queue_type>::IsEmpty(void) const
80 {
81 return head==tail;
82 }
83
84 template <class queue_type>
85 inline unsigned int Queue<queue_type>::AllocationSize( void ) const
86 {
87 return allocation_size;
88 }
89
90 template <class queue_type>
91 Queue<queue_type>::Queue()
92 {
93 //allocation_size = 16;
94 //array = SLNet::OP_NEW_ARRAY<queue_type>(allocation_size, _FILE_AND_LINE_ );
95 allocation_size = 0;
96 array=0;
97 head = 0;
98 tail = 0;
99 }
100
101 template <class queue_type>
102 Queue<queue_type>::~Queue()
103 {
104 if (allocation_size>0)
105 SLNet::OP_DELETE_ARRAY(array, _FILE_AND_LINE_);
106 }
107
108 template <class queue_type>
109 inline queue_type Queue<queue_type>::Pop( void )
110 {
111 #ifdef _DEBUG
112 RakAssert( head != tail);
113 #endif
114 //head=(head+1) % allocation_size;
115
116 if ( ++head == allocation_size )
117 head = 0;
118
119 if ( head == 0 )
120 return ( queue_type ) array[ allocation_size -1 ];
121
122 return ( queue_type ) array[ head -1 ];
123 }
124
125 template <class queue_type>
126 inline queue_type Queue<queue_type>::PopTail( void )
127 {
128 #ifdef _DEBUG
129 RakAssert( head != tail );
130 #endif
131 if (tail!=0)
132 {
133 --tail;
134 return ( queue_type ) array[ tail ];
135 }
136 else
137 {
138 tail=allocation_size-1;
139 return ( queue_type ) array[ tail ];
140 }
141 }
142
143 template <class queue_type>
144 inline queue_type Queue<queue_type>::PopDeref( void )
145 {
146 if ( ++head == allocation_size )
147 head = 0;
148
149 queue_type q;
150 if ( head == 0 )
151 {
152 q=array[ allocation_size -1 ];
153 array[ allocation_size -1 ]=0;
154 return q;
155 }
156
157 q=array[ head -1 ];
158 array[ head -1 ]=0;
159 return q;
160 }
161
162 template <class queue_type>
163 void Queue<queue_type>::PushAtHead( const queue_type& input, unsigned index, const char *file, unsigned int line )
164 {
165 RakAssert(index <= Size());
166
167 // Just force a reallocation, will be overwritten
168 Push(input, file, line );
169
170 if (Size()==1)
171 return;
172
173 unsigned writeIndex, readIndex, trueWriteIndex, trueReadIndex;
174 writeIndex=Size()-1;
175 readIndex=writeIndex-1;
176 while (readIndex >= index)
177 {
178 if ( head + writeIndex >= allocation_size )
179 trueWriteIndex = head + writeIndex - allocation_size;
180 else
181 trueWriteIndex = head + writeIndex;
182
183 if ( head + readIndex >= allocation_size )
184 trueReadIndex = head + readIndex - allocation_size;
185 else
186 trueReadIndex = head + readIndex;
187
188 array[trueWriteIndex]=array[trueReadIndex];
189
190 if (readIndex==0)
191 break;
192 writeIndex--;
193 readIndex--;
194 }
195
196 if ( head + index >= allocation_size )
197 trueWriteIndex = head + index - allocation_size;
198 else
199 trueWriteIndex = head + index;
200
201 array[trueWriteIndex]=input;
202 }
203
204
205 template <class queue_type>
206 inline queue_type Queue<queue_type>::Peek( void ) const
207 {
208 #ifdef _DEBUG
209 RakAssert( head != tail );
210 #endif
211
212 return ( queue_type ) array[ head ];
213 }
214
215 template <class queue_type>
216 inline queue_type Queue<queue_type>::PeekTail( void ) const
217 {
218 #ifdef _DEBUG
219 RakAssert( head != tail );
220 #endif
221 if (tail!=0)
222 return ( queue_type ) array[ tail-1 ];
223 else
224 return ( queue_type ) array[ allocation_size-1 ];
225 }
226
227 template <class queue_type>
228 void Queue<queue_type>::Push( const queue_type& input, const char *file, unsigned int line )
229 {
230 if ( allocation_size == 0 )
231 {
232 array = SLNet::OP_NEW_ARRAY<queue_type>(16, file, line );
233 head = 0;
234 tail = 1;
235 array[ 0 ] = input;
236 allocation_size = 16;
237 return ;
238 }
239
240 array[ tail++ ] = input;
241
242 if ( tail == allocation_size )
243 tail = 0;
244
245 if ( tail == head )
246 {
247 // unsigned int index=tail;
248
249 // Need to allocate more memory.
250 queue_type * new_array;
251 new_array = SLNet::OP_NEW_ARRAY<queue_type>((int)allocation_size * 2, file, line );
252 #ifdef _DEBUG
253 RakAssert( new_array );
254 #endif
255 if (new_array==0)
256 return;
257
258 for ( unsigned int counter = 0; counter < allocation_size; ++counter )
259 new_array[ counter ] = array[ ( head + counter ) % ( allocation_size ) ];
260
261 head = 0;
262
263 tail = allocation_size;
264
265 allocation_size *= 2;
266
267 // Delete the old array and move the pointer to the new array
268 SLNet::OP_DELETE_ARRAY(array, file, line);
269
270 array = new_array;
271 }
272
273 }
274
275 template <class queue_type>
276 Queue<queue_type>::Queue( const Queue& original_copy )
277 {
278 // Allocate memory for copy
279
280 if ( original_copy.Size() == 0 )
281 {
282 allocation_size = 0;
283 }
284
285 else
286 {
287 array = SLNet::OP_NEW_ARRAY<queue_type >( original_copy.Size() + 1 , _FILE_AND_LINE_ );
288
289 for ( unsigned int counter = 0; counter < original_copy.Size(); ++counter )
290 array[ counter ] = original_copy.array[ ( original_copy.head + counter ) % ( original_copy.allocation_size ) ];
291
292 head = 0;
293
294 tail = original_copy.Size();
295
296 allocation_size = original_copy.Size() + 1;
297 }
298 }
299
300 template <class queue_type>
301 bool Queue<queue_type>::operator= ( const Queue& original_copy )
302 {
303 if ( ( &original_copy ) == this )
304 return false;
305
306 Clear(_FILE_AND_LINE_);
307
308 // Allocate memory for copy
309 if ( original_copy.Size() == 0 )
310 {
311 allocation_size = 0;
312 }
313
314 else
315 {
316 array = SLNet::OP_NEW_ARRAY<queue_type >( original_copy.Size() + 1 , _FILE_AND_LINE_ );
317
318 for ( unsigned int counter = 0; counter < original_copy.Size(); ++counter )
319 array[ counter ] = original_copy.array[ ( original_copy.head + counter ) % ( original_copy.allocation_size ) ];
320
321 head = 0;
322
323 tail = original_copy.Size();
324
325 allocation_size = original_copy.Size() + 1;
326 }
327
328 return true;
329 }
330
331 template <class queue_type>
332 inline void Queue<queue_type>::Clear ( const char *file, unsigned int line )
333 {
334 if ( allocation_size == 0 )
335 return ;
336
337 if (allocation_size > 32)
338 {
339 SLNet::OP_DELETE_ARRAY(array, file, line);
340 allocation_size = 0;
341 }
342
343 head = 0;
344 tail = 0;
345 }
346
347 template <class queue_type>
348 void Queue<queue_type>::Compress ( const char *file, unsigned int line )
349 {
350 queue_type* new_array;
351 unsigned int newAllocationSize;
352 if (allocation_size==0)
353 return;
354
355 newAllocationSize=1;
356 while (newAllocationSize <= Size())
357 newAllocationSize<<=1; // Must be a better way to do this but I'm too dumb to figure it out quickly :)
358
359 new_array = SLNet::OP_NEW_ARRAY<queue_type >(newAllocationSize, file, line );
360
361 for (unsigned int counter=0; counter < Size(); ++counter)
362 new_array[counter] = array[(head + counter)%(allocation_size)];
363
364 tail=Size();
365 allocation_size=newAllocationSize;
366 head=0;
367
368 // Delete the old array and move the pointer to the new array
369 SLNet::OP_DELETE_ARRAY(array, file, line);
370 array=new_array;
371 }
372
373 template <class queue_type>
374 bool Queue<queue_type>::Find ( const queue_type &q )
375 {
376 if ( allocation_size == 0 )
377 return false;
378
379 unsigned int counter = head;
380
381 while ( counter != tail )
382 {
383 if ( array[ counter ] == q )
384 return true;
385
386 counter = ( counter + 1 ) % allocation_size;
387 }
388
389 return false;
390 }
391
392 template <class queue_type>
393 void Queue<queue_type>::ClearAndForceAllocation( int size, const char *file, unsigned int line )
394 {
395 SLNet::OP_DELETE_ARRAY(array, file, line);
396 if (size>0)
397 array = SLNet::OP_NEW_ARRAY<queue_type>(size, file, line );
398 else
399 array=0;
400 allocation_size = size;
401 head = 0;
402 tail = 0;
403 }
404
405 template <class queue_type>
406 inline queue_type& Queue<queue_type>::operator[] ( unsigned int position ) const
407 {
408 #ifdef _DEBUG
409 RakAssert( position < Size() );
410 #endif
411 //return array[(head + position) % allocation_size];
412
413 if ( head + position >= allocation_size )
414 return array[ head + position - allocation_size ];
415 else
416 return array[ head + position ];
417 }
418
419 template <class queue_type>
420 void Queue<queue_type>::RemoveAtIndex( unsigned int position )
421 {
422 #ifdef _DEBUG
423 RakAssert( position < Size() );
424 RakAssert( head != tail );
425 #endif
426
427 if ( head == tail || position >= Size() )
428 return ;
429
430 unsigned int index;
431
432 unsigned int next;
433
434 //index = (head + position) % allocation_size;
435 if ( head + position >= allocation_size )
436 index = head + position - allocation_size;
437 else
438 index = head + position;
439
440 //next = (index + 1) % allocation_size;
441 next = index + 1;
442
443 if ( next == allocation_size )
444 next = 0;
445
446 while ( next != tail )
447 {
448 // Overwrite the previous element
449 array[ index ] = array[ next ];
450 index = next;
451 //next = (next + 1) % allocation_size;
452
453 if ( ++next == allocation_size )
454 next = 0;
455 }
456
457 // Move the tail back
458 if ( tail == 0 )
459 tail = allocation_size - 1;
460 else
461 --tail;
462 }
463 } // End namespace
464
465 #endif
466