Eneboo - Documentación para desarrolladores
|
00001 // -*- C++ -*- 00002 00003 /* 00004 00005 Heap Layers: An Extensible Memory Allocation Infrastructure 00006 00007 Copyright (C) 2000-2003 by Emery Berger 00008 http://www.cs.umass.edu/~emery 00009 emery@cs.umass.edu 00010 00011 This program is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 This program is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU General Public License for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with this program; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 */ 00026 00027 #ifndef _OBJECTMANAGER_H_ 00028 #define _OBJECTMANAGER_H_ 00029 00030 #include <stdlib.h> // for size_t 00031 00032 namespace HL { 00033 00034 class EmptyHeap {}; 00035 00036 // The default object manager class. 00037 00038 00039 template <class SuperHeap> 00040 class ObjectManagerBase : public SuperHeap { 00041 public: 00042 00043 // Return the object's size. 00044 inline static size_t getSize (void * const ptr) { 00045 return getObject(ptr)->getSize(); 00046 } 00047 00048 protected: 00049 00051 00052 // Return the object's overhead (i.e., in the header). 00053 inline static size_t getOverhead (void * const) { 00054 return sizeof(AllocatedObject); 00055 } 00056 00057 // Is this object free? 00058 inline static bool isFree (void * const ptr) { 00059 return getObject(ptr)->isFree(); 00060 } 00061 00062 00063 // Is the previous object free? 00064 inline static bool isPrevFree (void * const ptr) { 00065 return getObject(ptr)->isPrevFree(); 00066 } 00067 00068 // Previous object 00069 inline static void * getPrev (void * const ptr) { 00070 return getObject(ptr)->getPrev(); 00071 } 00072 00073 00074 // Next object 00075 inline static void * getNext (void * const ptr) { 00076 return getObject(ptr)->getNext(); 00077 } 00078 00079 00081 00082 // Instantiate an object in a given space. 00083 inline static void * makeObject (void * buf, size_t prevSize, size_t sz) { 00084 AllocatedObject * p = new (buf) AllocatedObject (prevSize, sz); 00085 return (void *) (p + 1); 00086 } 00087 00088 inline static size_t getPrevSize (void * const ptr) { 00089 return getObject(ptr)->getPrevSize(); 00090 } 00091 00092 // Mark this item as free. 00093 inline static void markFree (void * ptr) { 00094 getObject(ptr)->markFree(); 00095 getObject(getNext(ptr))->markPrevFree(); 00096 } 00097 00098 // Mark this item as in use. 00099 inline static void markInUse (void * ptr) { 00100 getObject(ptr)->markInUse(); 00101 getObject(getNext(ptr))->markPrevInUse(); 00102 } 00103 00104 00105 private: 00106 00107 00108 // Change the object's size. 00109 inline static void setSize (void * ptr, size_t sz) { 00110 getObject(ptr)->setSize (sz); 00111 } 00112 00113 // Change the object's size. 00114 inline static void setPrevSize (void * ptr, size_t sz) { 00115 getObject(ptr)->setPrevSize (sz); 00116 } 00117 00118 00119 // All objects managed by this object manager 00120 // are prefaced by a header of type AllocatedObject, 00121 // which manages the size of the current & previous allocated objects. 00122 00123 class AllocatedObject { 00124 friend class ObjectManagerBase<SuperHeap>; 00125 private: 00126 inline AllocatedObject (size_t prevSize, size_t sz) 00127 : _sz (sz) 00128 , _prevSize (prevSize) 00129 #if 0 //ndef NDEBUG 00130 , _magic ((double) MAGIC_NUMBER) 00131 #endif 00132 { 00133 // Set the prev size of the next object. 00134 ((AllocatedObject *) ((char *) (this + 1) + _sz))->setPrevSize (sz); 00135 assert (!isFree()); 00136 assert (!isPrevFree()); 00137 } 00138 00139 inline size_t getSize (void) const { 00140 assert (isValid()); 00141 return _sz & ~FREE_BIT; 00142 } 00143 inline void setSize (size_t sz) { 00144 assert (sz > 0); 00145 assert (isValid()); 00146 _sz = sz; 00147 } 00148 inline bool isFree (void) const { 00149 assert (isValid()); 00150 return _sz & FREE_BIT; 00151 } 00152 inline bool isPrevFree (void) const { 00153 assert (isValid()); 00154 return _prevSize & FREE_BIT; 00155 } 00156 // Return the previous object (in address order). 00157 inline void * getPrev (void) const { 00158 assert (isValid()); 00159 return (void *) ((char *) this - getPrevSize()); 00160 } 00161 // Return the next object (in address order). 00162 inline void * getNext (void) const { 00163 assert (isValid()); 00164 return (void *) ((char *) (this+2) + getSize()); 00165 } 00166 inline size_t getPrevSize (void) const { 00167 assert (isValid()); 00168 return _prevSize & ~FREE_BIT; 00169 } 00170 inline void markFree (void) { 00171 assert (isValid()); 00172 markFree(_sz); 00173 } 00174 inline void markInUse (void) { 00175 assert (isValid()); 00176 markInUse(_sz); 00177 } 00178 inline void markPrevFree (void) { 00179 assert (isValid()); 00180 markFree(_prevSize); 00181 } 00182 inline void markPrevInUse (void) { 00183 assert (isValid()); 00184 markInUse(_prevSize); 00185 } 00186 inline void setPrevSize (size_t sz) { 00187 assert (sz > 0); 00188 assert (isValid()); 00189 _prevSize = sz; 00190 } 00191 private: 00192 enum { FREE_BIT = 1 }; 00193 enum { MAGIC_NUMBER = 0 }; 00194 00195 int isValid (void) const { 00196 #if 0 // ndef NDEBUG 00197 return (_magic == (double) MAGIC_NUMBER); 00198 #else 00199 return 1; //((_sz & 6) == 0); 00200 #endif 00201 } 00202 00203 inline static void markInUse (size_t& sz) { 00204 sz &= ~FREE_BIT; 00205 } 00206 00207 inline static void markFree (size_t& sz) { 00208 sz |= FREE_BIT; 00209 } 00210 00211 00212 // The size of the previous object (that is, right behind this one). 00213 size_t _prevSize; 00214 00215 // We steal the last bit of the size field 00216 // for free/in use. 00217 // If the last bit is 1, the object is free. 00218 // Otherwise, it's in use. 00219 size_t _sz; 00220 00221 #if 0 //ndef NDEBUG 00222 double _magic; 00223 #endif 00224 }; 00225 00226 protected: 00227 inline static AllocatedObject * getObject (void * const ptr) { 00228 return (AllocatedObject *) ptr - 1; 00229 } 00230 }; 00231 00232 00233 00234 template <class SuperHeap> 00235 class ProvideObjectManager : public ObjectManagerBase<SuperHeap> { 00236 public: 00237 inline void * malloc (size_t sz) { 00238 assert (sz > 0); 00239 void * ptr = SuperHeap::malloc (sz + getOverhead(NULL)); 00240 if (ptr == NULL) 00241 return NULL; 00242 void * p = makeObject (ptr, getPrevSize((char *) ptr + getOverhead(NULL)), sz); 00243 markInUse (p); 00244 assert (getSize(p) >= sz); 00245 assert (getPrevSize(getNext(p)) == getSize(p)); 00246 return p; 00247 } 00248 00249 inline void free (void * ptr) { 00250 int ps = getPrevSize(getNext(ptr)); 00251 int sz = getSize(ptr); 00252 assert (getPrevSize(getNext(ptr)) == getSize(ptr)); 00253 markFree (ptr); 00254 SuperHeap::free ((void *) getObject(ptr)); 00255 } 00256 }; 00257 00258 00259 template <class SuperHeap> 00260 class ObjectManager : public ObjectManagerBase<SuperHeap> { 00261 public: 00262 #if 1 00263 inline void * malloc (size_t sz) { 00264 void * p = SuperHeap::malloc (sz); 00265 if (p != NULL) { 00266 assert (getSize(p) >= sz); 00267 //setPrevSize(getNext(p), getSize(p)); 00268 markInUse (p); 00269 } 00270 return p; 00271 } 00272 00273 inline void free (void * ptr) { 00274 markFree (ptr); 00275 SuperHeap::free (ptr); 00276 } 00277 #endif 00278 }; 00279 00280 00281 00282 class ObjectManagerWrapper { 00283 public: 00284 template <class S> 00285 class Manager : public ObjectManager<S> {}; 00286 }; 00287 00288 00289 class ProvideObjectManagerWrapper { 00290 public: 00291 template <class S> 00292 class Manager : public ProvideObjectManager<S> {}; 00293 }; 00294 00295 template <class S> 00296 class NOP : public S {}; 00297 00298 class NullObjectManagerWrapper { 00299 public: 00300 template <class S> 00301 class Manager : public NOP<S> {}; 00302 }; 00303 00304 00305 /* 00306 00307 This ObjectManagerHeap is a tortuous work-around 00308 for a bug in Visual C++ 6.0 that finally allows us 00309 to pass ObjectManager wrappers as template arguments. 00310 00311 This can go away once support is added for nested templates. 00312 00313 Wrappers look like this: 00314 00315 class Wrap1 { 00316 public: 00317 template <class S> 00318 class Manager : public ObjectManager<S> {}; 00319 }; 00320 00321 */ 00322 00323 00324 #if __SVR4 00325 template <class SuperHeap, class OMWrapper> 00326 class SelectObjectManagerHeap { 00327 public: 00328 class TheHeap : public OMWrapper::Manager<SuperHeap> {}; 00329 }; 00330 00331 #else 00332 template <class SuperHeap, class OMWrapper> 00333 class SelectObjectManagerHeap { 00334 public: 00335 class ObjectManagerHeapProxy1 : public OMWrapper { 00336 public: 00337 template <class A> class Manager {}; 00338 }; 00339 00340 class ObjectManagerHeapProxy2 : public ObjectManagerHeapProxy1 { 00341 private: 00342 typedef typename OMWrapper::Manager<SuperHeap> ManageFoo; 00343 public: 00344 class ManageMe : public ManageFoo {}; 00345 }; 00346 00347 class TheHeap : public ObjectManagerHeapProxy2::ManageMe {}; 00348 }; 00349 #endif 00350 00351 }; 00352 00353 #endif 00354