gwnavruntime/kernel/SF_ListAlloc.h Source File

SF_ListAlloc.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 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_ListAlloc.h
11 Content : A simple and fast allocator for "recyclable" elements.
12 Created : 2008
13 Authors : MaximShemanarev
14 
15 **************************************************************************/
16 
17 #ifndef INC_KY_Kernel_ListAlloc_H
18 #define INC_KY_Kernel_ListAlloc_H
19 
21 
22 namespace Kaim {
23 
24 // ***** ListAllocBase
25 //
26 // A simple and fast allocator for "recyclable" elements. It allocates
27 // pages of elements of "PageSize" and never performs reallocations,
28 // maintaining minimal memory fragmentation. The allocator also keeps
29 // a linked list of freed elements.
30 //
31 // The allocator is mostly used together with List and List2.
32 //
33 // Function Alloc() first checks the freeMem list, and if not empty returns
34 // the first freeMem element. If the freeMem list is empty the function
35 // allocates elements in pages, creating new pages as needed.
36 //
37 // Function Free(T* element) recycles the element adding it into the
38 // freeMem list.
39 //
40 // The constructors and destructors are called in Alloc() and Free()
41 // respectively. Constructors and destructors are not called in the
42 // "POD" modification of the allocator.
43 //
44 // Function ClearAndRelease() and the allocator's destructor DO NOT call
45 // elements' destructors! They just freeMem the allocated pages.
46 //
47 // The use policy is that if you Alloc() the element you must Free() it.
48 // The reason of such a behavior is that it's impossible to determine
49 // whether or not the element in the page was destroyed, so that,
50 // ClearAndRelease cannot call the elements' destructors, otherwise
51 // there will be "double destruction".
52 //------------------------------------------------------------------------
53 template<class T, int PageSize, class Allocator> class ListAllocBase
54 {
55 public:
56  typedef T ValueType;
57  typedef Allocator AllocatorType;
58  typedef ListAllocBase<T, PageSize, Allocator> SelfType;
59 
60 private:
61  struct PageType
62  {
63  ValueType Data[PageSize];
64  PageType* pNext;
65  };
66 
67  struct NodeType
68  {
69  NodeType* pNext;
70  };
71 protected:
72  ListAllocBase(void* p) :
73  FirstPage(0),
74  LastPage(0),
75  NumElementsInPage(PageSize),
76  FirstEmptySlot(0),
77  pHeapOrPtr(p)
78  {
79  KY_COMPILER_ASSERT(sizeof(T) >= sizeof(T*));
80  }
81 
82 public:
83  ListAllocBase() :
84  FirstPage(0),
85  LastPage(0),
86  NumElementsInPage(PageSize),
87  FirstEmptySlot(0)
88  {
89  KY_COMPILER_ASSERT(sizeof(T) >= sizeof(T*));
90  pHeapOrPtr = this;
91  }
92 
93  ~ListAllocBase()
94  {
95  freeMem();
96  }
97 
98  void ClearAndRelease()
99  {
100  freeMem();
101  FirstPage = 0;
102  LastPage = 0;
103  NumElementsInPage = PageSize;
104  FirstEmptySlot = 0;
105  }
106 
107  UPInt GetNumBytes() const
108  {
109  UPInt numBytes = 0;
110  const PageType* page = FirstPage;
111  while (page)
112  {
113  numBytes += sizeof(PageType);
114  page = page->pNext;
115  }
116  return numBytes;
117  }
118 
119  T* Alloc()
120  {
121  T* ret = allocate();
122  Allocator::Construct(ret);
123  return ret;
124  }
125 
126  T* Alloc(const T& v)
127  {
128  T* ret = allocate();
129  Allocator::Construct(ret, v);
130  return ret;
131  }
132 
133  template<class S>
134  T* AllocAlt(const S& v)
135  {
136  ValueType* ret = allocate();
137  Allocator::ConstructAlt(ret, v);
138  return ret;
139  }
140 
141  void Free(T* element)
142  {
143  Allocator::Destruct(element);
144  ((NodeType*)element)->pNext = FirstEmptySlot;
145  FirstEmptySlot = (NodeType*)element;
146  }
147 
148 private:
149  // Copying is prohibited
150  ListAllocBase(const SelfType&);
151  const SelfType& operator = (SelfType&);
152 
153  inline T* allocate()
154  {
155  if (FirstEmptySlot)
156  {
157  T* ret = (T*)FirstEmptySlot;
158  FirstEmptySlot = FirstEmptySlot->pNext;
159  return ret;
160  }
161  if (NumElementsInPage < PageSize)
162  {
163  return &LastPage->Data[NumElementsInPage++];
164  }
165 
166  PageType* next = (PageType*)Allocator::Alloc(pHeapOrPtr, sizeof(PageType), __FILE__, __LINE__);
167  next->pNext = 0;
168  if (LastPage)
169  LastPage->pNext = next;
170  else
171  FirstPage = next;
172  LastPage = next;
173  NumElementsInPage = 1;
174  return &LastPage->Data[0];
175  }
176 
177  inline void freeMem()
178  {
179  PageType* page = FirstPage;
180  while (page)
181  {
182  PageType* next = page ->pNext;
183  Allocator::Free(page);
184  page = next;
185  }
186  }
187 
188  PageType* FirstPage;
189  PageType* LastPage;
190  unsigned NumElementsInPage;
191  NodeType* FirstEmptySlot;
192  void* pHeapOrPtr;
193 };
194 
195 
196 
197 // ***** ListAllocPOD
198 //
199 // Paged list allocator for objects that DOES NOT require
200 // construction/destruction. Constructors and destructors are not called!
201 // Global heap is in use.
202 //------------------------------------------------------------------------
203 template<class T, int PageSize=127, int SID=Stat_Default_Mem>
204 class ListAllocPOD :
205  public ListAllocBase<T, PageSize, AllocatorGH_POD<T, SID> >
206 {
207 public:
208  typedef ListAllocPOD<T, PageSize, SID> SelfType;
209  typedef T ValueType;
210  typedef AllocatorGH_POD<T, SID> AllocatorType;
211 };
212 
213 
214 // ***** ListAlloc
215 //
216 // Paged list allocator array for objects that require
217 // explicit construction/destruction.
218 // Global heap is in use.
219 //------------------------------------------------------------------------
220 template<class T, int PageSize=127, int SID=Stat_Default_Mem>
221 class ListAlloc :
222  public ListAllocBase<T, PageSize, AllocatorGH<T, SID> >
223 {
224 public:
225  typedef ListAlloc<T, PageSize, SID> SelfType;
226  typedef T ValueType;
227  typedef AllocatorGH<T, SID> AllocatorType;
228 };
229 
230 
231 // ***** ListAllocLH_POD
232 //
233 // Paged list allocator for objects that DOES NOT require
234 // construction/destruction. Constructors and destructors are not called!
235 // Local heap is in use.
236 //------------------------------------------------------------------------
237 template<class T, int PageSize=127, int SID=Stat_Default_Mem>
238 class ListAllocLH_POD :
239  public ListAllocBase<T, PageSize, AllocatorLH_POD<T, SID> >
240 {
241 public:
242  typedef ListAllocLH_POD<T, PageSize, SID> SelfType;
243  typedef T ValueType;
244  typedef AllocatorLH_POD<T, SID> AllocatorType;
245 };
246 
247 
248 // ***** ListAllocLH
249 //
250 // Paged list allocator for objects that require
251 // explicit construction/destruction.
252 // Local heap is in use.
253 //------------------------------------------------------------------------
254 template<class T, int PageSize=127, int SID=Stat_Default_Mem>
255 class ListAllocLH :
256  public ListAllocBase<T, PageSize, AllocatorLH<T, SID> >
257 {
258 public:
259  typedef ListAllocLH<T, PageSize, SID> SelfType;
260  typedef T ValueType;
261  typedef AllocatorLH<T, SID> AllocatorType;
262 };
263 
264 // ***** ListAllocDH_POD
265 //
266 // Paged list allocator for objects that DOES NOT require
267 // construction/destruction. Constructors and destructors are not called!
268 // The specified heap is in use.
269 //------------------------------------------------------------------------
270 template<class T, int PageSize=127, int SID=Stat_Default_Mem>
271 class ListAllocDH_POD :
272  public ListAllocBase<T, PageSize, AllocatorDH_POD<T, SID> >
273 {
274 public:
275  typedef ListAllocDH_POD<T, PageSize, SID> SelfType;
276  typedef T ValueType;
277  typedef AllocatorDH_POD<T, SID> AllocatorType;
278 
279  ListAllocDH_POD(void* pHeap)
280  : ListAllocBase<T, PageSize, AllocatorDH_POD<T, SID> >(pHeap) {}
281 };
282 
283 
284 // ***** ListAllocDH
285 //
286 // Paged list allocator for objects that require
287 // explicit construction/destruction.
288 // The specified heap is in use.
289 //------------------------------------------------------------------------
290 template<class T, int PageSize=127, int SID=Stat_Default_Mem>
291 class ListAllocDH :
292  public ListAllocBase<T, PageSize, AllocatorDH<T, SID> >
293 {
294 public:
295  typedef ListAllocDH<T, PageSize, SID> SelfType;
296  typedef T ValueType;
297  typedef AllocatorDH<T, SID> AllocatorType;
298 
299  ListAllocDH(void* pHeap)
300  : ListAllocBase<T, PageSize, AllocatorDH<T, SID> >(pHeap) {}
301 };
302 
303 } // Scaleform
304 
305 #endif
306 
Definition: gamekitcrowddispersion.h:20