gwnavgeneration/common/growingpool.h Source File

growingpool.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 #pragma once
9 
10 
13 
14 
15 namespace Kaim
16 {
17 
18 /*
19 // To browse the GrowingPool use the following code
20 MyClass* chunk = nullptr;
21 KyUInt32 countInChunk = 0;
22 for (KyUInt32 chunkIdx = 0; chunkIdx < pool.GetChunkCount(); ++chunkIdx)
23 {
24  pool.GetChunk(chunkIdx, chunk, countInChunk);
25  for (KyUInt32 idx = 0; idx < countInChunk; ++idx)
26  {
27  MyClass& obj = chunk[idx];
28  }
29 }
30 */
31 template <class T>
32 class GrowingPool
33 {
34  KY_DEFINE_NEW_DELETE_OPERATORS(Stat_Default_Mem)
35 public:
36  explicit GrowingPool(MemoryHeap* heap, KyUInt32 byteCountInChunk = 0);
37 
38  ~GrowingPool() { Release(); }
39 
40  // Does call T constructor.
41  T* GetNew();
42 
43  void Clear();
44 
45  void Release();
46 
47  KyUInt32 GetElementCount() const { return m_elementCount; }
48  KyUInt32 GetChunkCount() const { return m_chunkCount; }
49  KyUInt32 ByteCountAllocated() const { return m_byteCountAllocated; }
50 
51  void GetChunk(KyUInt32 idx, T*& chunk, KyUInt32& countInChunk);
52 
53 
54 private:
55  KyUInt32 CalculateElementCountFromByteCount(KyInt32 byteCount);
56  KyUInt32 CalculateWordCount(KyInt32 elementCount);
57 
58 private:
59  KyArrayDH_POD<T*> m_chunks;
60  KyUInt32 m_chunkCount;
61  KyUInt32 m_elementCount;
62  KyUInt32 m_maxWordCountInChunk;
63  KyUInt32 m_maxElementCountInChunk;
64  KyUInt32 m_elementCountInLastChunk;
65  KyUInt32 m_byteCountAllocated;
66  MemoryHeap* m_heap;
67 };
68 
69 
70 template<class T>
71 inline GrowingPool<T>::GrowingPool(MemoryHeap* heap, KyUInt32 byteCountInChunk) : m_chunks(heap)
72 {
73  if (byteCountInChunk <= 0)
74  byteCountInChunk = 512 * 1024; // 512 KB by default
75 
76  m_chunks.Resize(16);
77  for (KyUInt32 i = 0 ; i < m_chunks.GetCount(); ++i)
78  m_chunks[i] = nullptr;
79 
80  m_chunkCount = 0;
81  m_elementCount = 0;
82  m_maxElementCountInChunk = CalculateElementCountFromByteCount(byteCountInChunk);
83  m_maxWordCountInChunk = CalculateWordCount(m_maxElementCountInChunk);
84  m_elementCountInLastChunk = m_maxElementCountInChunk;
85  m_byteCountAllocated = 0;
86  m_heap = heap;
87 }
88 
89 
90 template<class T>
91 inline T* GrowingPool<T>::GetNew()
92 {
93  if (m_elementCountInLastChunk == m_maxElementCountInChunk) // we reached the end of the current chunk
94  {
95  KyUInt32 oldSize = m_chunks.GetCount();
96  if (m_chunkCount >= oldSize) // no more chunks in m_chunks, resize it
97  {
98  m_chunks.Resize(oldSize * 2);
99  for (KyUInt32 i = oldSize; i < m_chunks.GetCount(); ++i)
100  m_chunks[i] = nullptr;
101  }
102 
103  if (m_chunks[m_chunkCount] == nullptr) // need to allocate a new chunk
104  {
105  m_chunks[m_chunkCount] = (T*)KY_HEAP_MALLOC(m_heap, KyUInt32, m_maxWordCountInChunk, MemStat_NavDataGen);
106  m_byteCountAllocated += m_maxWordCountInChunk * sizeof(KyUInt32);
107  }
108 
109  ++m_chunkCount;
110  m_elementCountInLastChunk = 0;
111  }
112 
113  ++m_elementCount;
114 
115  T* ptr = &m_chunks[m_chunkCount - 1][m_elementCountInLastChunk];
116  ::new(ptr) T;
117 
118  ++m_elementCountInLastChunk;
119  return ptr;
120 }
121 
122 
123 template<class T>
124 inline void GrowingPool<T>::Clear()
125 {
126  // call destructor on elements
127  T* chunk = nullptr;
128  KyUInt32 countInChunk = 0;
129 
130  for (KyUInt32 chunkIdx = 0; chunkIdx < GetChunkCount(); ++chunkIdx)
131  {
132  GetChunk(chunkIdx, chunk, countInChunk);
133  for (KyUInt32 idx = 0; idx < countInChunk; ++idx)
134  chunk[idx].~T();
135  }
136 
137  m_elementCount = 0;
138  m_chunkCount = 0;
139  m_elementCountInLastChunk = m_maxElementCountInChunk;
140 }
141 
142 
143 template<class T>
144 inline void GrowingPool<T>::Release()
145 {
146  Clear();
147 
148  for (KyUInt32 i = 0; i < m_chunks.GetCount(); ++i)
149  KY_FREE(m_chunks[i]);
150 
151  m_chunks.ClearAndRelease();
152  m_byteCountAllocated = 0;
153 }
154 
155 
156 template<class T>
157 KY_INLINE void GrowingPool<T>::GetChunk(KyUInt32 idx, T*& chunk, KyUInt32& countInChunk)
158 {
159  chunk = m_chunks[idx];
160  countInChunk = (idx != m_chunkCount - 1) ? m_maxElementCountInChunk : m_elementCountInLastChunk;
161 }
162 
163 
164 template<class T>
165 KY_INLINE KyUInt32 GrowingPool<T>::CalculateElementCountFromByteCount(KyInt32 byteCount)
166 {
167  return (byteCount - 1) / (KyInt32)sizeof (T) + 1;
168 }
169 
170 template<class T>
171 KY_INLINE KyUInt32 GrowingPool<T>::CalculateWordCount(KyInt32 elementCount)
172 {
173  return (elementCount * (KyInt32)sizeof (T) - 1) / sizeof(KyUInt32) + 1;
174 }
175 
176 } // namespace Kaim
177 
std::uint32_t KyUInt32
uint32_t
Definition: types.h:29
#define KY_DEFINE_NEW_DELETE_OPERATORS(MemStat)
This macro defines new and delete operators.
Definition: memory.h:132
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
std::int32_t KyInt32
int32_t
Definition: types.h:24