E:/p4/sw/physx/PxShared/1.0/trunk/src/foundation/include/PsPool.h
Go to the documentation of this file.00001 // This code contains NVIDIA Confidential Information and is disclosed to you 00002 // under a form of NVIDIA software license agreement provided separately to you. 00003 // 00004 // Notice 00005 // NVIDIA Corporation and its licensors retain all intellectual property and 00006 // proprietary rights in and to this software and related documentation and 00007 // any modifications thereto. Any use, reproduction, disclosure, or 00008 // distribution of this software and related documentation without an express 00009 // license agreement from NVIDIA Corporation is strictly prohibited. 00010 // 00011 // ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES 00012 // NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO 00013 // THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, 00014 // MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. 00015 // 00016 // Information and code furnished is believed to be accurate and reliable. 00017 // However, NVIDIA Corporation assumes no responsibility for the consequences of use of such 00018 // information or for any infringement of patents or other rights of third parties that may 00019 // result from its use. No license is granted by implication or otherwise under any patent 00020 // or patent rights of NVIDIA Corporation. Details are subject to change without notice. 00021 // This code supersedes and replaces all information previously supplied. 00022 // NVIDIA Corporation products are not authorized for use as critical 00023 // components in life support devices or systems without express written approval of 00024 // NVIDIA Corporation. 00025 // 00026 // Copyright (c) 2008-2014 NVIDIA Corporation. All rights reserved. 00027 // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. 00028 // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. 00029 00030 #ifndef PSFOUNDATION_PSPOOL_H 00031 #define PSFOUNDATION_PSPOOL_H 00032 00033 #include "PsArray.h" 00034 #include "PsSort.h" 00035 #include "PsBasicTemplates.h" 00036 #include "PsBasicTemplates.h" 00037 #include "PsInlineArray.h" 00038 00039 namespace physx 00040 { 00041 namespace shdfnd 00042 { 00043 00047 template <class T, class Alloc = typename AllocatorTraits<T>::Type> 00048 class PoolBase : public UserAllocated, public Alloc 00049 { 00050 PX_NOCOPY(PoolBase) 00051 protected: 00052 PoolBase(const Alloc& alloc, uint32_t elementsPerSlab, uint32_t slabSize) 00053 : Alloc(alloc) 00054 , mSlabs(alloc) 00055 , mElementsPerSlab(elementsPerSlab) 00056 , mUsed(0) 00057 , mSlabSize(slabSize) 00058 , mFreeElement(0) 00059 { 00060 PX_COMPILE_TIME_ASSERT(sizeof(T) >= sizeof(size_t)); 00061 } 00062 00063 public: 00064 ~PoolBase() 00065 { 00066 if(mUsed) 00067 disposeElements(); 00068 00069 for(void** slabIt = mSlabs.begin(), *slabEnd = mSlabs.end(); slabIt != slabEnd; ++slabIt) 00070 Alloc::deallocate(*slabIt); 00071 } 00072 00073 // Allocate space for single object 00074 PX_INLINE T* allocate() 00075 { 00076 if(mFreeElement == 0) 00077 allocateSlab(); 00078 T* p = reinterpret_cast<T*>(mFreeElement); 00079 mFreeElement = mFreeElement->mNext; 00080 mUsed++; 00085 #if PX_CHECKED 00086 for(uint32_t i = 0; i < sizeof(T); ++i) 00087 reinterpret_cast<uint8_t*>(p)[i] = 0xcd; 00088 #endif 00089 return p; 00090 } 00091 00092 // Put space for a single element back in the lists 00093 PX_INLINE void deallocate(T* p) 00094 { 00095 if(p) 00096 { 00097 PX_ASSERT(mUsed); 00098 mUsed--; 00099 push(reinterpret_cast<FreeList*>(p)); 00100 } 00101 } 00102 00103 PX_INLINE T* construct() 00104 { 00105 T* t = allocate(); 00106 return t ? new (t) T() : 0; 00107 } 00108 00109 template <class A1> 00110 PX_INLINE T* construct(A1& a) 00111 { 00112 T* t = allocate(); 00113 return t ? new (t) T(a) : 0; 00114 } 00115 00116 template <class A1, class A2> 00117 PX_INLINE T* construct(A1& a, A2& b) 00118 { 00119 T* t = allocate(); 00120 return t ? new (t) T(a, b) : 0; 00121 } 00122 00123 template <class A1, class A2, class A3> 00124 PX_INLINE T* construct(A1& a, A2& b, A3& c) 00125 { 00126 T* t = allocate(); 00127 return t ? new (t) T(a, b, c) : 0; 00128 } 00129 00130 template <class A1, class A2, class A3> 00131 PX_INLINE T* construct(A1* a, A2& b, A3& c) 00132 { 00133 T* t = allocate(); 00134 return t ? new (t) T(a, b, c) : 0; 00135 } 00136 00137 template <class A1, class A2, class A3, class A4> 00138 PX_INLINE T* construct(A1& a, A2& b, A3& c, A4& d) 00139 { 00140 T* t = allocate(); 00141 return t ? new (t) T(a, b, c, d) : 0; 00142 } 00143 00144 template <class A1, class A2, class A3, class A4, class A5> 00145 PX_INLINE T* construct(A1& a, A2& b, A3& c, A4& d, A5& e) 00146 { 00147 T* t = allocate(); 00148 return t ? new (t) T(a, b, c, d, e) : 0; 00149 } 00150 00151 PX_INLINE void destroy(T* const p) 00152 { 00153 if(p) 00154 { 00155 p->~T(); 00156 deallocate(p); 00157 } 00158 } 00159 00160 protected: 00161 struct FreeList 00162 { 00163 FreeList* mNext; 00164 }; 00165 00166 // All the allocated slabs, sorted by pointer 00167 InlineArray<void*, 64, Alloc> mSlabs; 00168 00169 uint32_t mElementsPerSlab; 00170 uint32_t mUsed; 00171 uint32_t mSlabSize; 00172 00173 FreeList* mFreeElement; // Head of free-list 00174 00175 // Helper function to get bitmap of allocated elements 00176 00177 void push(FreeList* p) 00178 { 00179 p->mNext = mFreeElement; 00180 mFreeElement = p; 00181 } 00182 00183 // Allocate a slab and segregate it into the freelist 00184 void allocateSlab() 00185 { 00186 T* slab = reinterpret_cast<T*>(Alloc::allocate(mSlabSize, __FILE__, __LINE__)); 00187 00188 mSlabs.pushBack(slab); 00189 00190 // Build a chain of nodes for the freelist 00191 T* it = slab + mElementsPerSlab; 00192 while(--it >= slab) 00193 push(reinterpret_cast<FreeList*>(it)); 00194 } 00195 00196 /* 00197 Cleanup method. Go through all active slabs and call destructor for live objects, 00198 then free their memory 00199 */ 00200 void disposeElements() 00201 { 00202 Array<void*, Alloc> freeNodes(*this); 00203 while(mFreeElement) 00204 { 00205 freeNodes.pushBack(mFreeElement); 00206 mFreeElement = mFreeElement->mNext; 00207 } 00208 Alloc& alloc(*this); 00209 sort(freeNodes.begin(), freeNodes.size(), Less<void*>(), alloc); 00210 sort(mSlabs.begin(), mSlabs.size(), Less<void*>(), alloc); 00211 00212 typename Array<void*, Alloc>::Iterator slabIt = mSlabs.begin(), slabEnd = mSlabs.end(); 00213 for(typename Array<void*, Alloc>::Iterator freeIt = freeNodes.begin(); slabIt != slabEnd; ++slabIt) 00214 { 00215 for(T* tIt = reinterpret_cast<T*>(*slabIt), *tEnd = tIt + mElementsPerSlab; tIt != tEnd; ++tIt) 00216 { 00217 if(freeIt != freeNodes.end() && *freeIt == tIt) 00218 ++freeIt; 00219 else 00220 tIt->~T(); 00221 } 00222 } 00223 } 00224 00225 /* 00226 Go through all slabs and call destructor if the slab is empty 00227 */ 00228 void releaseEmptySlabs() 00229 { 00230 Array<void*, Alloc> freeNodes(*this); 00231 Array<void*, Alloc> slabNodes(mSlabs, *this); 00232 while(mFreeElement) 00233 { 00234 freeNodes.pushBack(mFreeElement); 00235 mFreeElement = mFreeElement->mNext; 00236 } 00237 00238 typename Array<void*, Alloc>::Iterator freeIt = freeNodes.begin(), freeEnd = freeNodes.end(), 00239 lastCheck = freeNodes.end() - mElementsPerSlab; 00240 00241 if(freeNodes.size() > mElementsPerSlab) 00242 { 00243 Alloc& alloc(*this); 00244 sort(freeNodes.begin(), freeNodes.size(), Less<void*>(), alloc); 00245 sort(slabNodes.begin(), slabNodes.size(), Less<void*>(), alloc); 00246 00247 mSlabs.clear(); 00248 for(void** slabIt = slabNodes.begin(), *slabEnd = slabNodes.end(); slabIt != slabEnd; ++slabIt) 00249 { 00250 while((freeIt < lastCheck) && (*slabIt > (*freeIt))) 00251 { 00252 push(reinterpret_cast<FreeList*>(*freeIt)); 00253 freeIt++; 00254 } 00255 00256 if(*slabIt == (*freeIt)) // the slab's first element in freeList 00257 { 00258 const size_t endSlabAddress = size_t(*slabIt) + mSlabSize; 00259 const size_t endFreeAddress = size_t(*(freeIt + mElementsPerSlab - 1)); 00260 if(endFreeAddress + sizeof(T) == endSlabAddress) 00261 { // all slab's element in freeList 00262 Alloc::deallocate(*slabIt); 00263 freeIt += mElementsPerSlab; 00264 continue; 00265 } 00266 } 00267 00268 mSlabs.pushBack(*slabIt); 00269 } 00270 } 00271 00272 while(freeIt != freeEnd) 00273 { 00274 push(reinterpret_cast<FreeList*>(*freeIt)); 00275 ++freeIt; 00276 } 00277 } 00278 }; 00279 00280 // original pool implementation 00281 template <class T, class Alloc = typename AllocatorTraits<T>::Type> 00282 class Pool : public PoolBase<T, Alloc> 00283 { 00284 public: 00285 Pool(const Alloc& alloc = Alloc(), uint32_t elementsPerSlab = 32) 00286 : PoolBase<T, Alloc>(alloc, elementsPerSlab, elementsPerSlab * sizeof(T)) 00287 { 00288 } 00289 }; 00290 00291 // allows specification of the slab size instead of the occupancy 00292 template <class T, uint32_t slabSize, class Alloc = typename AllocatorTraits<T>::Type> 00293 class Pool2 : public PoolBase<T, Alloc> 00294 { 00295 public: 00296 Pool2(const Alloc& alloc = Alloc()) : PoolBase<T, Alloc>(alloc, slabSize / sizeof(T), slabSize) 00297 { 00298 } 00299 }; 00300 00301 } // namespace shdfnd 00302 } // namespace physx 00303 00304 #endif // #ifndef PSFOUNDATION_PSPOOL_H
Generated on Tue Jul 28 14:21:55 2015 for NVIDIA(R) PsFoundation Reference by
![doxygen](doxygen.png)