Eneboo - Documentación para desarrolladores
src/hoard/src/heaplayers/experimental/objectmanager.h
Ir a la documentación de este archivo.
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 
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'