CrystalSpace

Public API Reference

csutil/allocator.h

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2006 by Frank Richter
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public
00015     License along with this library; if not, write to the Free
00016     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifndef __CS_CSUTIL_ALLOCATOR_H__
00020 #define __CS_CSUTIL_ALLOCATOR_H__
00021 
00026 #include "csutil/alignedalloc.h"
00027 #include "csutil/memdebug.h"
00028 
00032 namespace CS
00033 {
00034   namespace Memory
00035   {
00039     class AllocatorMalloc
00040     {
00041     #ifdef CS_MEMORY_TRACKER
00043       csMemTrackerInfo* mti;
00044     #endif
00045     public:
00046     #ifdef CS_MEMORY_TRACKER
00047       AllocatorMalloc() : mti (0) {}
00048     #endif
00050       CS_ATTRIBUTE_MALLOC void* Alloc (const size_t n)
00051       {
00052       #ifdef CS_MEMORY_TRACKER
00053         size_t* p = (size_t*)cs_malloc (n + sizeof (size_t));
00054         *p = n;
00055         p++;
00056         if (mti) mtiUpdateAmount (mti, 1, int (n));
00057         return p;
00058       #else
00059         return cs_malloc (n);
00060       #endif
00061       }
00063       void Free (void* p)
00064       {
00065       #ifdef CS_MEMORY_TRACKER
00066         size_t* x = (size_t*)p;
00067         x--;
00068         size_t allocSize = *x;
00069         cs_free (x);
00070         if (mti) mtiUpdateAmount (mti, -1, -int (allocSize));
00071       #else
00072         cs_free (p);
00073       #endif
00074       }
00076       void* Realloc (void* p, size_t newSize)
00077       {
00078       #ifdef CS_MEMORY_TRACKER
00079         if (p == 0) return Alloc (newSize);
00080         size_t* x = (size_t*)p;
00081         x--;
00082         if (mti) mtiUpdateAmount (mti, -1, -int (*x));
00083         size_t* np = (size_t*)cs_realloc (x, newSize + sizeof (size_t));
00084         *np = newSize;
00085         np++;
00086         if (mti) mtiUpdateAmount (mti, 1, int (newSize));
00087         return np;
00088       #else
00089         return cs_realloc (p, newSize);
00090       #endif
00091       }
00093       void SetMemTrackerInfo (const char* info)
00094       {
00095       #ifdef CS_MEMORY_TRACKER
00096         mti = mtiRegister (info);
00097       #else
00098         (void)info;
00099       #endif
00100       }
00101     };
00102     
00119     template<typename T, size_t N, class ExcessAllocator = AllocatorMalloc>
00120     class LocalBufferAllocator : public ExcessAllocator
00121     {
00122       static const size_t localSize = N * sizeof (T);
00123       uint8 localBuf[localSize];
00124     #ifdef CS_DEBUG
00125       bool allocation;
00126     #endif
00127     public:
00128     #ifdef CS_DEBUG
00129       LocalBufferAllocator () : allocation (false) {}
00130       LocalBufferAllocator (const ExcessAllocator& xalloc) : 
00131         ExcessAllocator (xalloc), allocation (false) {}
00132     #else
00133       LocalBufferAllocator () {}
00134       LocalBufferAllocator (const ExcessAllocator& xalloc) : 
00135         ExcessAllocator (xalloc) {}
00136     #endif
00137       T* Alloc (size_t allocSize)
00138       {
00139       #ifdef CS_DEBUG
00140         CS_ASSERT_MSG("LocalBufferAllocator only allows one allocation a time!",
00141           !allocation);
00142         allocation = true;
00143       #endif
00144         if (allocSize <= localSize)
00145           return (T*)localBuf;
00146         else
00147           return (T*)ExcessAllocator::Alloc (allocSize);
00148       }
00149     
00150       void Free (T* mem)
00151       {
00152       #ifdef CS_DEBUG
00153         CS_ASSERT_MSG("Free() without prior allocation",
00154           allocation);
00155         allocation = false;
00156       #endif
00157         if (mem != (T*)localBuf) ExcessAllocator::Free (mem);
00158       }
00159     
00160       // The 'relevantcount' parameter should be the number of items
00161       // in the old array that are initialized.
00162       void* Realloc (void* p, size_t newSize)
00163       {
00164       #ifdef CS_DEBUG
00165         CS_ASSERT_MSG("Realloc() without prior allocation",
00166           allocation);
00167       #endif
00168         if (p == localBuf)
00169         {
00170           if (newSize <= localSize)
00171             return p;
00172           else
00173           {
00174             p = ExcessAllocator::Alloc (newSize);
00175             memcpy (p, localBuf, localSize);
00176             return p;
00177           }
00178         }
00179         else
00180         {
00181           if (newSize <= localSize)
00182           {
00183             memcpy (localBuf, p, newSize);
00184             ExcessAllocator::Free (p);
00185             return localBuf;
00186           }
00187           else
00188             return ExcessAllocator::Realloc (p, newSize);
00189         }
00190       }
00191       using ExcessAllocator::SetMemTrackerInfo;
00192     };
00193     
00199     template <size_t A = 1>
00200     class AllocatorAlign
00201     {
00202     public:
00206       static inline CS_ATTRIBUTE_MALLOC void* Alloc (size_t size) 
00207       {
00208         return AlignedMalloc (size, A);
00209       }
00210 
00215       static inline void Free (void* p)
00216       {
00217         AlignedFree (p);
00218       }
00219 
00220       void* Realloc (void* p, size_t newSize)
00221       {
00222         return AlignedRealloc (p, newSize, A);
00223       }
00224 
00225       void SetMemTrackerInfo (const char* info)
00226       {
00227         (void)info;
00228       }
00229     };
00230 
00236     template<bool Reallocatable = true>
00237     class AllocatorNewChar
00238     {
00239     #ifdef CS_MEMORY_TRACKER
00241       csMemTrackerInfo* mti;
00242     #endif
00243     public:
00244     #ifdef CS_MEMORY_TRACKER
00245       AllocatorNewChar() : mti (0) {}
00246     #endif
00248       CS_ATTRIBUTE_MALLOC void* Alloc (const size_t n)
00249       {
00250         // Note that with memtracking we store the alloc'ed size anyway.
00251       #ifndef CS_MEMORY_TRACKER
00252         if (!Reallocatable)
00253         {
00254           return new char[n];
00255         }
00256       #endif
00257         size_t* p = (size_t*)new char[n + sizeof (size_t)];
00258         *p = n;
00259         p++;
00260       #ifdef CS_MEMORY_TRACKER
00261         if (mti) mtiUpdateAmount (mti, 1, int (n));
00262       #endif
00263         return p;
00264       }
00266       void Free (void* p)
00267       {
00268       #ifndef CS_MEMORY_TRACKER
00269         if (!Reallocatable)
00270         {
00271           delete[] (char*)p;
00272           return;
00273         }
00274       #endif
00275         size_t* x = (size_t*)p;
00276         x--;
00277         size_t allocSize = *x;
00278         delete[] (char*)x;
00279       #ifdef CS_MEMORY_TRACKER
00280         if (mti) mtiUpdateAmount (mti, -1, -int (allocSize));
00281       #else
00282         (void)allocSize;
00283       #endif
00284       }
00286       void* Realloc (void* p, size_t newSize)
00287       {
00288         CS_ASSERT_MSG("Realloc() called on non-reallocatable AllocatorNewChar",
00289           Reallocatable);
00290         if (p == 0) return Alloc (newSize);
00291         size_t* x = (size_t*)p;
00292         x--;
00293         size_t oldSize = *x;
00294       #ifdef CS_MEMORY_TRACKER
00295         if (mti) mtiUpdateAmount (mti, -1, -int (oldSize));
00296       #endif
00297         size_t* np = Alloc (newSize);
00298         if (newSize < oldSize)
00299           memcpy (np, p, newSize);
00300         else
00301           memcpy (np, p, oldSize);
00302         Free (p);
00303       #ifdef CS_MEMORY_TRACKER
00304         if (mti) mtiUpdateAmount (mti, 1, int (newSize));
00305       #endif
00306         return np;
00307       }
00309       void SetMemTrackerInfo (const char* info)
00310       {
00311       #ifdef CS_MEMORY_TRACKER
00312         mti = mtiRegister (info);
00313       #else
00314         (void)info;
00315       #endif
00316       }
00317     };
00318 
00329     template<typename T>
00330     class AllocatorNew
00331     {
00332     public:
00334       CS_ATTRIBUTE_MALLOC void* Alloc (const size_t n)
00335       {
00336         return new T[((n + sizeof(T) - 1) / sizeof(T)) * sizeof(T)];
00337       }
00339       void Free (void* p)
00340       {
00341         delete[] (T*)p;
00342       }
00344       void* Realloc (void* p, size_t newSize)
00345       {
00346         CS_ASSERT_MSG("Realloc() called on AllocatorNew", false);
00347         return 0;
00348       }
00350       void SetMemTrackerInfo (const char* /*info*/)
00351       {
00352       }
00353     };
00354 
00355     
00361     template<typename T, typename Allocator>
00362     struct AllocatorPointerWrapper : public Allocator
00363     {
00365       T* p;
00366 
00367       AllocatorPointerWrapper () {}
00368       AllocatorPointerWrapper (const Allocator& alloc) : 
00369         Allocator (alloc) {}
00370       AllocatorPointerWrapper (T* p) : p (p) {}
00371       AllocatorPointerWrapper (const Allocator& alloc, T* p) : 
00372         Allocator (alloc), p (p) {}
00373     };
00374 
00375   } // namespace Memory
00376 } // namespace CS
00377 
00380 #endif // __CS_CSUTIL_ALLOCATOR_H__

Generated for Crystal Space 1.2.1 by doxygen 1.5.3