RavEngine
Loading...
Searching...
No Matches
CmPreallocatingPool.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef CM_PREALLOCATING_POOL_H
30#define CM_PREALLOCATING_POOL_H
31
32#include "foundation/Px.h"
33#include "foundation/PxUserAllocated.h"
34#include "foundation/PxSort.h"
35#include "foundation/PxArray.h"
36
37namespace physx
38{
39namespace Cm
40{
41
43{
44public:
45 PX_FORCE_INLINE PreallocatingRegion() : mMemory(NULL), mFirstFree(NULL), mNbElements(0) {}
46
47 void init(PxU32 maxElements, PxU32 elementSize, const char* typeName)
48 {
49 mFirstFree = NULL;
50 mNbElements = 0;
51 PX_ASSERT(typeName);
52 PX_UNUSED(typeName);
53 mMemory = reinterpret_cast<PxU8*>(PX_ALLOC(sizeof(PxU8)*elementSize*maxElements, typeName?typeName:"SceneSim Pool")); // ### addActor alloc
54 PX_ASSERT(elementSize*maxElements>=sizeof(void*));
55 }
56
57 void reset()
58 {
59 PX_FREE(mMemory);
60 }
61
62 PX_FORCE_INLINE PxU8* allocateMemory(PxU32 maxElements, PxU32 elementSize)
63 {
64 if(mFirstFree)
65 {
66 PxU8* recycled = reinterpret_cast<PxU8*>(mFirstFree);
67
68 void** recycled32 = reinterpret_cast<void**>(recycled);
69 mFirstFree = *recycled32;
70
71 return recycled;
72 }
73 else
74 {
75 if(mNbElements==maxElements)
76 return NULL; // Out of memory
77
78 const PxU32 freeIndex = mNbElements++;
79 return mMemory + freeIndex * elementSize;
80 }
81 }
82
83 void deallocateMemory(PxU32 maxElements, PxU32 elementSize, PxU8* element)
84 {
85 PX_ASSERT(element);
86 PX_ASSERT(element>=mMemory && element<mMemory + maxElements * elementSize);
87 PX_UNUSED(elementSize);
88 PX_UNUSED(maxElements);
89
90 void** recycled32 = reinterpret_cast<void**>(element);
91 *recycled32 = mFirstFree;
92
93 mFirstFree = element;
94 }
95
96 PX_FORCE_INLINE bool operator < (const PreallocatingRegion& p) const
97 {
98 return mMemory < p.mMemory;
99 }
100
101 PX_FORCE_INLINE bool operator > (const PreallocatingRegion& p) const
102 {
103 return mMemory > p.mMemory;
104 }
105
106 PxU8* mMemory;
107 void* mFirstFree;
108 PxU32 mNbElements;
109};
110
111
112
114{
115 public:
116 PreallocatingRegionManager(PxU32 maxElements, PxU32 elementSize, const char* typeName)
117 : mMaxElements (maxElements)
118 , mElementSize (elementSize)
119 , mActivePoolIndex (0)
120 , mPools ("MyPoolManagerPools")
121 , mNeedsSorting (true)
122 , mTypeName (typeName)
123 {
125 tmp.init(maxElements, elementSize, mTypeName);
126 mPools.pushBack(tmp);
127 }
128
130 {
131 const PxU32 nbPools = mPools.size();
132 for(PxU32 i=0;i<nbPools;i++)
133 mPools[i].reset();
134 }
135
136 void preAllocate(PxU32 n)
137 {
138 if(!n)
139 return;
140
141 const PxU32 nbPools = mPools.size();
142 const PxU32 maxElements = mMaxElements;
143 const PxU32 elementSize = mElementSize;
144 PxU32 availableSpace = nbPools * maxElements;
145
146 while(n>availableSpace)
147 {
149 tmp.init(maxElements, elementSize, mTypeName);
150 mPools.pushBack(tmp);
151
152 availableSpace += maxElements;
153 }
154 }
155
156 PX_FORCE_INLINE PxU8* allocateMemory()
157 {
158 PX_ASSERT(mActivePoolIndex<mPools.size());
159 PxU8* memory = mPools[mActivePoolIndex].allocateMemory(mMaxElements, mElementSize);
160 return memory ? memory : searchForMemory();
161 }
162
163 void deallocateMemory(PxU8* element)
164 {
165 if(!element)
166 return;
167
168 if(mNeedsSorting)
169 PxSort(mPools.begin(), mPools.size());
170
171 const PxU32 maxElements = mMaxElements;
172 const PxU32 elementSize = mElementSize;
173 const PxU32 slabSize = maxElements * elementSize;
174 const PxU32 nbPools = mPools.size();
175
176 // O(log n) search
177 int first = 0;
178 int last = int(nbPools-1);
179
180 while(first<=last)
181 {
182 const int mid = (first+last)>>1;
183
184 PreallocatingRegion& candidate = mPools[PxU32(mid)];
185 if(contains(candidate.mMemory, slabSize, element))
186 {
187 candidate.deallocateMemory(maxElements, elementSize, element);
188
189 // when we sorted earlier we trashed the active index, but at least this region has a free element
190 if(mNeedsSorting)
191 mActivePoolIndex = PxU32(mid);
192
193 mNeedsSorting = false;
194 return;
195 }
196
197 if(candidate.mMemory<element)
198 first = mid+1;
199 else
200 last = mid-1;
201 }
202
203 PX_ASSERT(0);
204 }
205
206
207private:
208
210 PxU8* searchForMemory()
211 {
212 const PxU32 nbPools = mPools.size();
213 const PxU32 activePoolIndex = mActivePoolIndex;
214 const PxU32 maxElements = mMaxElements;
215 const PxU32 elementSize = mElementSize;
216
217
218 for(PxU32 i=0;i<nbPools;i++)
219 {
220 if(i==activePoolIndex)
221 continue;
222
223 PxU8* memory = mPools[i].allocateMemory(maxElements, elementSize);
224 if(memory)
225 {
226 mActivePoolIndex = i;
227 return memory;
228 }
229 }
230
231 mActivePoolIndex = nbPools;
232 mNeedsSorting = true;
233
235 tmp.init(maxElements, elementSize, mTypeName);
236
237 PreallocatingRegion& newPool = mPools.pushBack(tmp); // ### addActor alloc (StaticSim, ShapeSim, SceneQueryShapeData)
238 return newPool.allocateMemory(maxElements, elementSize);
239 }
240
241
242
243 PX_FORCE_INLINE bool contains(PxU8* memory, const PxU32 slabSize, PxU8* element)
244 {
245 return element>=memory && element<memory+slabSize;
246 }
247
248
249
250 const PxU32 mMaxElements;
251 const PxU32 mElementSize;
252 PxU32 mActivePoolIndex;
253
255 bool mNeedsSorting;
256 const char* mTypeName;
257};
258
259template<class T>
261{
263
264public:
265 PreallocatingPool(PxU32 maxElements, const char* typeName) : mPool(maxElements, sizeof(T), typeName)
266 {
267 }
268
270 {
271 }
272
273 PX_FORCE_INLINE void preAllocate(PxU32 n)
274 {
275 mPool.preAllocate(n);
276 }
277
278 PX_INLINE T* allocate()
279 {
280 return reinterpret_cast<T*>(mPool.allocateMemory());
281 }
282
283 PX_FORCE_INLINE T* allocateAndPrefetch()
284 {
285 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
286 PxPrefetch(t, sizeof(T));
287 return t;
288 }
289
290 PX_INLINE T* construct()
291 {
292 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
293 return t ? PX_PLACEMENT_NEW(t, T()) : NULL;
294 }
295
296 template<class A1>
297 PX_INLINE T* construct(A1& a)
298 {
299 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
300 return t ? PX_PLACEMENT_NEW(t, T(a)) : NULL;
301 }
302
303 template<class A1, class A2>
304 PX_INLINE T* construct(A1& a, A2& b)
305 {
306 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
307 return t ? PX_PLACEMENT_NEW(t, T(a,b)) : NULL;
308 }
309
310 template<class A1, class A2, class A3>
311 PX_INLINE T* construct(A1& a, A2& b, A3& c)
312 {
313 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
314 return t ? PX_PLACEMENT_NEW(t, T(a,b,c)) : NULL;
315 }
316
317 template<class A1, class A2, class A3, class A4>
318 PX_INLINE T* construct(A1& a, A2& b, A3& c, A4& d)
319 {
320 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
321 return t ? PX_PLACEMENT_NEW(t, T(a,b,c,d)) : NULL;
322 }
323
324 template<class A1, class A2, class A3, class A4, class A5>
325 PX_INLINE T* construct(A1& a, A2& b, A3& c, A4& d, A5& e)
326 {
327 T* t = reinterpret_cast<T*>(mPool.allocateMemory());
328 return t ? PX_PLACEMENT_NEW(t, T(a,b,c,d,e)) : NULL;
329 }
330
332
333 PX_INLINE T* construct(T* t)
334 {
335 PX_ASSERT(t);
336 return PX_PLACEMENT_NEW(t, T());
337 }
338
339 template<class A1>
340 PX_INLINE T* construct(T* t, A1& a)
341 {
342 PX_ASSERT(t);
343 return PX_PLACEMENT_NEW(t, T(a));
344 }
345
346 template<class A1, class A2>
347 PX_INLINE T* construct(T* t, A1& a, A2& b)
348 {
349 PX_ASSERT(t);
350 return PX_PLACEMENT_NEW(t, T(a,b));
351 }
352
353 template<class A1, class A2, class A3>
354 PX_INLINE T* construct(T* t, A1& a, A2& b, A3& c)
355 {
356 PX_ASSERT(t);
357 return PX_PLACEMENT_NEW(t, T(a,b,c));
358 }
359
360 template<class A1, class A2, class A3, class A4>
361 PX_INLINE T* construct(T* t, A1& a, A2& b, A3& c, A4& d)
362 {
363 PX_ASSERT(t);
364 return PX_PLACEMENT_NEW(t, T(a,b,c,d));
365 }
366
367 template<class A1, class A2, class A3, class A4, class A5>
368 PX_INLINE T* construct(T* t, A1& a, A2& b, A3& c, A4& d, A5& e)
369 {
370 PX_ASSERT(t);
371 return PX_PLACEMENT_NEW(t, T(a,b,c,d,e));
372 }
373
374 PX_INLINE void destroy(T* const p)
375 {
376 if(p)
377 {
378 p->~T();
379 mPool.deallocateMemory(reinterpret_cast<PxU8*>(p));
380 }
381 }
382
383 PX_INLINE void releasePreallocated(T* const p)
384 {
385 if(p)
386 mPool.deallocateMemory(reinterpret_cast<PxU8*>(p));
387 }
388protected:
390};
391
392template<class T>
394{
395 PxArray<T*> mDeletedElems;
397public:
398 BufferedPreallocatingPool(PxU32 maxElements, const char* typeName) : PreallocatingPool<T>(maxElements, typeName)
399 {
400 }
401
402 PX_INLINE void destroy(T* const p)
403 {
404 if (p)
405 {
406 p->~T();
407 mDeletedElems.pushBack(p);
408 }
409 }
410
411 void processPendingDeletedElems()
412 {
413 for (PxU32 i = 0; i < mDeletedElems.size(); ++i)
414 this->mPool.deallocateMemory(reinterpret_cast<PxU8*>(mDeletedElems[i]));
415 mDeletedElems.clear();
416 }
417
418
419};
420
421
422
423
424} // namespace Cm
425
426}
427
428#endif
Definition CmPreallocatingPool.h:394
Definition CmPreallocatingPool.h:261
Definition CmPreallocatingPool.h:114
Definition CmPreallocatingPool.h:43
Definition PxArray.h:53
PX_FORCE_INLINE uint32_t size() const
Definition PxArray.h:242
PX_INLINE void clear()
Definition PxArray.h:250
PX_FORCE_INLINE T & pushBack(const T &a)
Definition PxArray.h:296
Definition PxUserAllocated.h:43
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_INLINE
Definition PxPreprocessor.h:320
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_FORCE_INLINE void PxPrefetch(const void *ptr, uint32_t count=1)
Definition PxUnixIntrinsics.h:91