csutil/blockallocator.h
Go to the documentation of this file.00001 /* 00002 Crystal Space Generic Object Block Allocator 00003 Copyright (C) 2005 by Eric Sunshine <sunshine@sunshineco.com> 00004 (C) 2006 by Frank Richter 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public 00017 License along with this library; if not, write to the Free 00018 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 */ 00020 #ifndef __CSUTIL_BLOCKALLOCATOR_H__ 00021 #define __CSUTIL_BLOCKALLOCATOR_H__ 00022 00027 #include "csutil/fixedsizeallocator.h" 00028 #include "csutil/metautils.h" 00029 #include "csutil/custom_new_disable.h" 00030 00037 template<typename T> 00038 class csBlockAllocatorDisposeDelete 00039 { 00040 public: 00044 template<typename BA> 00045 csBlockAllocatorDisposeDelete (const BA&, bool legit) 00046 { (void)legit; } 00048 void Dispose (void* p) 00049 { 00050 ((T*)p)->~T(); 00051 } 00052 }; 00053 00058 template<typename T> 00059 class csBlockAllocatorDisposeLeaky 00060 { 00061 bool doWarn; 00062 #ifdef CS_DEBUG 00063 const char* parentClass; 00064 const void* parent; 00065 size_t count; 00066 #endif 00067 public: 00068 #ifdef CS_DEBUG 00069 00076 template<typename BA> 00077 csBlockAllocatorDisposeLeaky (const BA& ba, bool legit) : 00078 doWarn (!legit), parentClass (typeid(BA).name()), parent (&ba), 00079 count (0) 00080 { 00081 } 00082 #else 00083 template<typename BA> 00084 csBlockAllocatorDisposeLeaky (const BA&, bool legit) : doWarn (!legit) 00085 { } 00086 #endif 00087 ~csBlockAllocatorDisposeLeaky() 00088 { 00089 #ifdef CS_DEBUG 00090 if ((count > 0) && doWarn) 00091 { 00092 csPrintfErr("%s %p leaked %zu objects.\n", parentClass, (void*)this, 00093 count); 00094 } 00095 #endif 00096 } 00098 void Dispose (void* p) 00099 { 00100 if (!doWarn) ((T*)p)->~T(); 00101 #ifdef CS_DEBUG 00102 count++; 00103 #endif 00104 } 00105 }; 00106 00110 template<typename T> 00111 struct csBlockAllocatorSizeObject 00112 { 00113 static const unsigned int value = sizeof(T); 00114 }; 00115 00119 template<typename T, unsigned int Alignment> 00120 struct csBlockAllocatorSizeObjectAlign 00121 { 00122 static const unsigned int value = CS::Meta::AlignSize<T, Alignment>::value; 00123 }; 00141 template <class T, 00142 typename Allocator = CS::Memory::AllocatorMalloc, 00143 typename ObjectDispose = csBlockAllocatorDisposeDelete<T>, 00144 typename SizeComputer = csBlockAllocatorSizeObject<T> 00145 > 00146 class csBlockAllocator : 00147 public csFixedSizeAllocator< 00148 SizeComputer::value, 00149 Allocator> 00150 { 00151 public: 00152 typedef csBlockAllocator<T, Allocator, ObjectDispose, SizeComputer> ThisType; 00153 typedef T ValueType; 00154 typedef Allocator AllocatorType; 00155 00156 protected: 00157 typedef csFixedSizeAllocator<SizeComputer::value, Allocator> superclass; 00158 00159 private: 00160 void* Alloc (size_t /*n*/) { return 0; } // Illegal 00161 void* Alloc (void* /*p*/, size_t /*newSize*/) { return 0; } // Illegal 00162 void SetMemTrackerInfo (const char* /*info*/) { } // Illegal 00163 public: 00183 csBlockAllocator(size_t nelem = 32) : superclass (nelem) 00184 { 00185 #ifdef CS_MEMORY_TRACKER 00186 superclass::blocks.SetMemTrackerInfo (typeid(*this).name()); 00187 #endif 00188 } 00189 00193 ~csBlockAllocator() 00194 { 00195 ObjectDispose dispose (*this, false); 00196 DisposeAll (dispose); 00197 } 00198 00204 void Empty () 00205 { 00206 ObjectDispose dispose (*this, true); 00207 FreeAll (dispose); 00208 } 00209 00215 void DeleteAll () 00216 { 00217 ObjectDispose dispose (*this, true); 00218 DisposeAll (dispose); 00219 } 00220 00225 T* Alloc () 00226 { 00227 return new (superclass::Alloc()) T; 00228 } 00229 00234 template<typename A1, typename A2> 00235 T* Alloc (A1& a1, A2& a2) 00236 { 00237 return new (superclass::Alloc()) T (a1, a2); 00238 } 00239 00244 template<typename A1, typename A2, typename A3> 00245 T* Alloc (A1& a1, A2& a2, A3& a3) 00246 { 00247 return new (superclass::Alloc()) T (a1, a2, a3); 00248 } 00249 00254 template<typename A1> 00255 T* Alloc (A1& a1) 00256 { 00257 return new (superclass::Alloc()) T (a1); 00258 } 00259 00264 void Free (T* p) 00265 { 00266 ObjectDispose dispose (*this, true); 00267 superclass::Free (dispose, p); 00268 } 00274 bool TryFree (T* p) 00275 { 00276 ObjectDispose dispose (*this, true); 00277 return superclass::TryFree (dispose, p); 00278 } 00279 }; 00280 00281 namespace CS 00282 { 00283 namespace Memory 00284 { 00290 template <class T, 00291 typename Allocator = AllocatorMalloc, 00292 typename ObjectDispose = csBlockAllocatorDisposeDelete<T>, 00293 typename SizeComputer = csBlockAllocatorSizeObject<T> 00294 > 00295 class BlockAllocatorSafe : 00296 public AllocatorSafe<csBlockAllocator<T, Allocator, ObjectDispose, 00297 SizeComputer> > 00298 { 00299 protected: 00300 typedef csBlockAllocator<T, Allocator, 00301 ObjectDispose, SizeComputer> WrappedAllocatorType; 00302 typedef AllocatorSafe<WrappedAllocatorType> AllocatorSafeType; 00303 public: 00304 BlockAllocatorSafe (size_t nelem = 32) : AllocatorSafeType (nelem) 00305 { 00306 } 00307 00308 void Empty () 00309 { 00310 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00311 WrappedAllocatorType::Empty (); 00312 } 00313 00314 void DeleteAll () 00315 { 00316 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00317 WrappedAllocatorType::DeleteAll (); 00318 } 00319 00320 void Compact() 00321 { 00322 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00323 WrappedAllocatorType::Compact(); 00324 } 00325 00326 T* Alloc () 00327 { 00328 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00329 return WrappedAllocatorType::Alloc (); 00330 } 00331 00332 template<typename A1, typename A2> 00333 T* Alloc (A1& a1, A2& a2) 00334 { 00335 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00336 return WrappedAllocatorType::Alloc (a1, a2); 00337 } 00338 00339 template<typename A1, typename A2, typename A3> 00340 T* Alloc (A1& a1, A2& a2, A3& a3) 00341 { 00342 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00343 return WrappedAllocatorType::Alloc (a1, a2, a3); 00344 } 00345 00346 template<typename A1> 00347 T* Alloc (A1& a1) 00348 { 00349 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00350 return WrappedAllocatorType::Alloc (a1); 00351 } 00352 00353 void Free (T* p) 00354 { 00355 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00356 WrappedAllocatorType::Free (p); 00357 } 00358 bool TryFree (T* p) 00359 { 00360 CS::Threading::RecursiveMutexScopedLock lock (AllocatorSafeType::mutex); 00361 return WrappedAllocatorType::TryFree (p); 00362 } 00363 }; 00364 } // namespace Memory 00365 } // namespace CS 00366 00369 #include "csutil/custom_new_enable.h" 00370 00371 #endif // __CSUTIL_BLOCKALLOCATOR_H__
Generated for Crystal Space 2.0 by doxygen 1.6.1