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 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 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<typename T, typename Allocator> 00237 struct AllocatorPointerWrapper : public Allocator 00238 { 00240 T* p; 00241 00242 AllocatorPointerWrapper () {} 00243 AllocatorPointerWrapper (const Allocator& alloc) : 00244 Allocator (alloc) {} 00245 AllocatorPointerWrapper (T* p) : p (p) {} 00246 AllocatorPointerWrapper (const Allocator& alloc, T* p) : 00247 Allocator (alloc), p (p) {} 00248 }; 00249 } // namespace Memory 00250 } // namespace CS 00251 00254 #endif // __CS_CSUTIL_ALLOCATOR_H__
Generated for Crystal Space by doxygen 1.4.7