gwnavruntime/kernel/SF_ArrayPaged.h Source File

SF_ArrayPaged.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 PublicHeader: Kernel
10 Filename : KY_ArrayPaged.h
11 Content :
12 Created :
13 Authors : Maxim Shemanarev, Sergey Sikorskiy
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_ArrayPaged_H
18 #define INC_KY_Kernel_ArrayPaged_H
19 
21 
22 namespace Kaim {
23 
24 
25 // ***** ConstructorPagedPOD
26 //
27 // A modification of ConstructorPOD with paged construction/destruction
28 // Used to avoid possible run-time overhead for POD types.
29 //------------------------------------------------------------------------
30 template<class T>
31 class ConstructorPagedPOD : public ConstructorPOD<T>
32 {
33 public:
34  static void ConstructArrayPaged(T**, UPInt, UPInt, UPInt, UPInt) {}
35  static void DestructArrayPaged (T**, UPInt, UPInt, UPInt, UPInt) {}
36 };
37 
38 
39 // ***** ConstructorPagedMov
40 //
41 // Correct C++ paged construction and destruction
42 //------------------------------------------------------------------------
43 template<class T>
44 class ConstructorPagedMov : public ConstructorMov<T>
45 {
46 public:
47  static void ConstructArrayPaged(T** pages, UPInt start, UPInt end, UPInt pageShift, UPInt pageMask)
48  {
49  for (UPInt i = start; i < end; ++i)
50  {
51  ConstructorMov<T>::Construct(pages[i >> pageShift] + (i & pageMask));
52  }
53  }
54 
55  static void DestructArrayPaged(T** pages, UPInt start, UPInt end, UPInt pageShift, UPInt pageMask)
56  {
57  for (UPInt i = end; i > start; --i)
58  {
59  ConstructorMov<T>::Destruct(pages[(i-1) >> pageShift] + ((i-1) & pageMask));
60  }
61  }
62 };
63 
64 
65 // ***** ConstructorPagedMovCC
66 //
67 // Correct C++ paged construction and destruction
68 //------------------------------------------------------------------------
69 template<typename T>
70 class ConstructorPagedMovCC : public ConstructorMov<T>
71 {
72 public:
73  const T& GetDefaultValue() const;
74  void ConstructArrayPaged(T** pages, UPInt start, UPInt end, UPInt pageShift, UPInt pageMask)
75  {
76  for (UPInt i = start; i < end; ++i)
77  {
78  ConstructorMov<T>::ConstructAlt(pages[i >> pageShift] + (i & pageMask), GetDefaultValue());
79  }
80  }
81 
82  static void DestructArrayPaged(T** pages, UPInt start, UPInt end, UPInt pageShift, UPInt pageMask)
83  {
84  for (UPInt i = end; i > start; --i)
85  {
86  ConstructorMov<T>::Destruct(pages[(i-1) >> pageShift] + ((i-1) & pageMask));
87  }
88  }
89 };
90 
91 
92 // ***** AllocatorPaged*
93 //
94 // Simple wraps as specialized allocators
95 //------------------------------------------------------------------------
96 template<class T, int SID> struct AllocatorPagedGH_POD : AllocatorBaseGH<SID>, ConstructorPagedPOD<T> {};
97 template<class T, int SID> struct AllocatorPagedGH : AllocatorBaseGH<SID>, ConstructorPagedMov<T> {};
98 
99 template<class T, int SID> struct AllocatorPagedLH_POD : AllocatorBaseLH<SID>, ConstructorPagedPOD<T> {};
100 template<class T, int SID> struct AllocatorPagedLH : AllocatorBaseLH<SID>, ConstructorPagedMov<T> {};
101 
102 template<typename T, int SID> struct AllocatorPagedCC : AllocatorBaseLH<SID>, ConstructorPagedMovCC<T> {};
103 
104 
105 // ***** ArrayPagedBase
106 //
107 // A simple class template to store data similar to std::deque
108 // It doesn't reallocate memory but instead, uses pages of data of size
109 // of (1 << PageSh), that is, power of two. The data is NOT contiguous in memory,
110 // so the only valid access methods are operator [], At(), ValueAt(), Front(), Back()
111 // The container guarantees the persistence of elements' addresses in memory,
112 // so the elements can be used in intrusive linked lists.
113 //
114 // Reallocs occur only when the pool of pointers to pages needs
115 // to be extended (happens very rarely). You can control the increment
116 // value by PtrPoolInc.
117 //
118 //-------------------
119 // The code of this class template was taken from the Anti-Grain Geometry
120 // Project and modified for the use by Scaleform.
121 // Permission to use without restrictions is hereby granted to
122 // Scaleform Corp. by the author of Anti-Grain Geometry Project.
123 //------------------------------------------------------------------------
124 template<class T, int PageSh, int PtrPoolInc, class Allocator>
125 class ArrayPagedBase : public Allocator
126 {
127 public:
128  enum PageConsts
129  {
130  PageShift = PageSh,
131  PageSize = 1 << PageShift,
132  PageMask = PageSize - 1
133  };
134 
135  typedef ArrayPagedBase<T, PageSh, PtrPoolInc, Allocator> SelfType;
136  typedef T ValueType;
137  typedef Allocator AllocatorType;
138 
139  ~ArrayPagedBase()
140  {
141  ClearAndRelease();
142  }
143 
144  ArrayPagedBase() :
145  Size(0),
146  NumPages(0),
147  MaxPages(0),
148  Pages(0)
149  {}
150 
151  void ClearAndRelease()
152  {
153  if(NumPages)
154  {
155  T** blk = Pages + NumPages - 1;
156  // It is actually numDataPages - 1. But this is OK.
157  const UPInt numDataPages = (Size > 0 ? Size >> PageShift : 0);
158  while(NumPages--)
159  {
160  const UPInt freeCount = (NumPages < numDataPages ? PageSize : (NumPages == numDataPages ? Size & PageMask : 0));
161  Allocator::DestructArray(*blk, freeCount);
162  Allocator::Free(*blk);
163  --blk;
164  }
165  Allocator::Free(Pages);
166  }
167  Size = NumPages = MaxPages = 0;
168  Pages = 0;
169  }
170 
171  void Clear()
172  {
173  Allocator::DestructArrayPaged(Pages, 0, Size, PageShift, PageMask);
174  Size = 0;
175  }
176 
177  void PushBack(const T& val)
178  {
179  Allocator::Construct(acquireDataPtr(), val);
180  ++Size;
181  }
182 
183  bool PushBackSafe(const T& val)
184  {
185  T* p = acquireDataPtrSafe();
186  if (!p) return false;
187  Allocator::Construct(p, val);
188  ++Size;
189  return true;
190  }
191 
192  template<class S>
193  void PushBackAlt(const S& val)
194  {
195  Allocator::ConstructAlt(acquireDataPtr(), val);
196  ++Size;
197  }
198 
199  void PopBack()
200  {
201  if(Size)
202  {
203  Allocator::Destruct(&At(Size - 1));
204  --Size;
205  }
206  }
207  void PopBack(UPInt count)
208  {
209  KY_ASSERT(Size >= count);
210  while(count)
211  {
212  Allocator::Destruct(&At(Size - 1));
213  --Size;
214  --count;
215  }
216  }
217 
218  T& PushDefault()
219  {
220  PushBack(T());
221  return Back();
222  }
223 
224  T Pop()
225  {
226  T t = Back();
227  PopBack();
228  return t;
229  }
230 
231 
232  UPInt GetCapacity() const
233  {
234  return NumPages << PageShift;
235  }
236 
237  UPInt GetNumBytes() const
238  {
239  return GetCapacity() * sizeof(T) + MaxPages * sizeof(T*);
240  }
241 
242  void Reserve(UPInt newCapacity)
243  {
244  if(newCapacity > GetCapacity())
245  {
246  UPInt newNumPages = (newCapacity + PageMask) >> PageShift;
247  for(UPInt i = NumPages; i < newNumPages; ++i)
248  allocatePage(i);
249  }
250  }
251 
252  void Resize(UPInt newSize)
253  {
254  if(newSize > Size)
255  {
256  UPInt newNumPages = (newSize + PageMask) >> PageShift;
257  for(UPInt i = NumPages; i < newNumPages; ++i)
258  allocatePage(i);
259  Allocator::ConstructArrayPaged(Pages, Size, newSize, PageShift, PageMask);
260  Size = newSize;
261  return;
262  }
263  if(newSize < Size)
264  {
265  Allocator::DestructArrayPaged(Pages, newSize, Size, PageShift, PageMask);
266  Size = newSize;
267  }
268  }
269 
270  void CutAt(UPInt newSize)
271  {
272  if(newSize < Size)
273  {
274  Allocator::DestructArrayPaged(Pages, newSize, Size, PageShift, PageMask);
275  Size = newSize;
276  }
277  }
278 
279  void InsertAt(UPInt pos, const T& val)
280  {
281  if(pos >= Size)
282  {
283  PushBack(val);
284  }
285  else
286  {
287  Allocator::Construct(acquireDataPtr());
288  ++Size;
289  UPInt i;
290  // TBD: Optimize page copying
291  for(i = Size-1; i > pos; --i)
292  {
293  At(i) = At(i - 1);
294  }
295  At(pos) = val;
296  }
297  }
298 
299  void RemoveAt(UPInt pos)
300  {
301  if(Size)
302  {
303  // TBD: Optimize page copying
304  for(++pos; pos < Size; pos++)
305  {
306  At(pos-1) = At(pos);
307  }
308  Allocator::Destruct(&At(Size - 1));
309  --Size;
310  }
311  }
312 
313  UPInt GetSize() const
314  {
315  return Size;
316  }
317 
318  const T& operator [] (UPInt i) const
319  {
320  return Pages[i >> PageShift][i & PageMask];
321  }
322 
323  T& operator [] (UPInt i)
324  {
325  return Pages[i >> PageShift][i & PageMask];
326  }
327 
328  const T& At(UPInt i) const
329  {
330  return Pages[i >> PageShift][i & PageMask];
331  }
332 
333  T& At(UPInt i)
334  {
335  return Pages[i >> PageShift][i & PageMask];
336  }
337 
338  T ValueAt(UPInt i) const
339  {
340  return Pages[i >> PageShift][i & PageMask];
341  }
342 
343  const T& Front() const
344  {
345  return Pages[0][0];
346  }
347 
348  T& Front()
349  {
350  return Pages[0][0];
351  }
352 
353  const T& Back() const
354  {
355  return At(Size - 1);
356  }
357 
358  T& Back()
359  {
360  return At(Size - 1);
361  }
362 
363 private:
364  // Copying is prohibited
365  ArrayPagedBase(const SelfType&);
366  const SelfType& operator = (const SelfType&);
367 
368  void allocatePage(UPInt nb)
369  {
370  if(nb >= MaxPages)
371  {
372  if(Pages)
373  {
374  Pages = (T**)Allocator::Realloc(
375  0, Pages, (MaxPages + PtrPoolInc) * sizeof(T*),
376  __FILE__, __LINE__);
377  }
378  else
379  {
380  Pages = (T**)Allocator::Alloc(
381  this, PtrPoolInc * sizeof(T*),
382  __FILE__, __LINE__);
383  }
384  MaxPages += PtrPoolInc;
385  }
386  Pages[nb] = (T*)Allocator::Alloc(this, PageSize * sizeof(T), __FILE__, __LINE__);
387  NumPages++;
388  }
389 
390  KY_INLINE T* acquireDataPtr()
391  {
392  UPInt np = Size >> PageShift;
393  if(np >= NumPages)
394  {
395  allocatePage(np);
396  }
397  return Pages[np] + (Size & PageMask);
398  }
399 
400  bool allocatePageSafe(UPInt nb)
401  {
402  if(nb >= MaxPages)
403  {
404  T** newPages;
405  if(Pages)
406  {
407  newPages = (T**)Allocator::Realloc(
408  0, Pages, (MaxPages + PtrPoolInc) * sizeof(T*),
409  __FILE__, __LINE__);
410  }
411  else
412  {
413  newPages = (T**)Allocator::Alloc(
414  this, PtrPoolInc * sizeof(T*),
415  __FILE__, __LINE__);
416  }
417  if (!newPages)
418  return false;
419  Pages = newPages;
420  MaxPages += PtrPoolInc;
421  }
422  Pages[nb] = (T*)Allocator::Alloc(this, PageSize * sizeof(T), __FILE__, __LINE__);
423  if (!Pages[nb])
424  return false;
425  NumPages++;
426  return true;
427  }
428 
429  KY_INLINE T* acquireDataPtrSafe()
430  {
431  UPInt np = Size >> PageShift;
432  if(np >= NumPages)
433  {
434  if (!allocatePageSafe(np))
435  return NULL;
436  }
437  return Pages[np] + (Size & PageMask);
438  }
439 
440  UPInt Size;
441  UPInt NumPages;
442  UPInt MaxPages;
443  T** Pages;
444 };
445 
446 
447 
448 
449 // ***** ArrayPagedPOD
450 //
451 // General purpose paged array for objects that DOES NOT require
452 // construction/destruction. Constructors and destructors are not called!
453 // Global heap is in use.
454 //------------------------------------------------------------------------
455 template<class T, int PageSh=6, int PtrPoolInc=64, int SID=Stat_Default_Mem>
456 class ArrayPagedPOD :
457  public ArrayPagedBase<T, PageSh, PtrPoolInc, AllocatorPagedGH_POD<T, SID> >
458 {
459 public:
460  typedef ArrayPagedPOD<T, PageSh, PtrPoolInc, SID> SelfType;
461  typedef T ValueType;
462  typedef AllocatorPagedGH_POD<T, SID> AllocatorType;
463 };
464 
465 
466 // ***** ArrayPaged
467 //
468 // General purpose paged array for objects that require
469 // explicit construction/destruction.
470 // Global heap is in use.
471 //------------------------------------------------------------------------
472 template<class T, int PageSh=6, int PtrPoolInc=64, int SID=Stat_Default_Mem>
473 class ArrayPaged :
474  public ArrayPagedBase<T, PageSh, PtrPoolInc, AllocatorPagedGH<T, SID> >
475 {
476 public:
477  typedef ArrayPaged<T, PageSh, PtrPoolInc, SID> SelfType;
478  typedef T ValueType;
479  typedef AllocatorPagedGH<T, SID> AllocatorType;
480 };
481 
482 
483 // ***** ArrayPagedLH_POD
484 //
485 // General purpose paged array for objects that require
486 // explicit construction/destruction.
487 // Local heap is in use.
488 //------------------------------------------------------------------------
489 template<class T, int PageSh=6, int PtrPoolInc=64, int SID=Stat_Default_Mem>
490 class ArrayPagedLH_POD :
491  public ArrayPagedBase<T, PageSh, PtrPoolInc, AllocatorPagedLH_POD<T, SID> >
492 {
493 public:
494  typedef ArrayPagedLH_POD<T, PageSh, PtrPoolInc, SID> SelfType;
495  typedef T ValueType;
496  typedef AllocatorPagedLH_POD<T, SID> AllocatorType;
497 };
498 
499 
500 // ***** ArrayPagedLH
501 //
502 // General purpose paged array for objects that DOES NOT require
503 // construction/destruction. Constructors and destructors are not called!
504 // Local heap is in use.
505 //------------------------------------------------------------------------
506 template<class T, int PageSh=6, int PtrPoolInc=64, int SID=Stat_Default_Mem>
507 class ArrayPagedLH :
508  public ArrayPagedBase<T, PageSh, PtrPoolInc, AllocatorPagedLH<T, SID> >
509 {
510 public:
511  typedef ArrayPagedLH<T, PageSh, PtrPoolInc, SID> SelfType;
512  typedef T ValueType;
513  typedef AllocatorPagedLH<T, SID> AllocatorType;
514 };
515 
516 // ***** ArrayPagedCC
517 //
518 // A modification of the array that uses the given default value to
519 // construct the elements. The constructors and destructors are
520 // properly called, the objects must be movable.
521 // Local heap is in use.
522 //------------------------------------------------------------------------
523 template<typename T, int PageSh=6, int PtrPoolInc=64, int SID=Stat_Default_Mem>
524 class ArrayPagedCC :
525  public ArrayPagedBase<T, PageSh, PtrPoolInc, AllocatorPagedCC<T, SID> >
526 {
527 public:
528  typedef ArrayPagedCC<T, PageSh, PtrPoolInc, SID> SelfType;
529  typedef T ValueType;
530  typedef AllocatorPagedCC<T, SID> AllocatorType;
531 
532 public:
533  ArrayPagedCC(const ValueType& v) : DefaultValue(v) {}
534 
535  const T& GetDefaultValue() const
536  {
537  return DefaultValue;
538  }
539 
540 private:
541  ValueType DefaultValue;
542 };
543 
544 } // Scaleform
545 
546 #endif
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17