00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 ) { return 0; }
00161 void* Alloc (void* , size_t ) { return 0; }
00162 void SetMemTrackerInfo (const char* ) { }
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 }
00365 }
00366
00369 #include "csutil/custom_new_enable.h"
00370
00371 #endif // __CSUTIL_BLOCKALLOCATOR_H__