00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #ifndef _OBJECTMANAGER_H_
00028 #define _OBJECTMANAGER_H_
00029
00030 #include <stdlib.h>
00031
00032 namespace HL {
00033
00034 class EmptyHeap {};
00035
00036
00037
00038
00039 template <class SuperHeap>
00040 class ObjectManagerBase : public SuperHeap {
00041 public:
00042
00043
00044 inline static size_t getSize (void * const ptr) {
00045 return getObject(ptr)->getSize();
00046 }
00047
00048 protected:
00049
00051
00052
00053 inline static size_t getOverhead (void * const) {
00054 return sizeof(AllocatedObject);
00055 }
00056
00057
00058 inline static bool isFree (void * const ptr) {
00059 return getObject(ptr)->isFree();
00060 }
00061
00062
00063
00064 inline static bool isPrevFree (void * const ptr) {
00065 return getObject(ptr)->isPrevFree();
00066 }
00067
00068
00069 inline static void * getPrev (void * const ptr) {
00070 return getObject(ptr)->getPrev();
00071 }
00072
00073
00074
00075 inline static void * getNext (void * const ptr) {
00076 return getObject(ptr)->getNext();
00077 }
00078
00079
00081
00082
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
00093 inline static void markFree (void * ptr) {
00094 getObject(ptr)->markFree();
00095 getObject(getNext(ptr))->markPrevFree();
00096 }
00097
00098
00099 inline static void markInUse (void * ptr) {
00100 getObject(ptr)->markInUse();
00101 getObject(getNext(ptr))->markPrevInUse();
00102 }
00103
00104
00105 private:
00106
00107
00108
00109 inline static void setSize (void * ptr, size_t sz) {
00110 getObject(ptr)->setSize (sz);
00111 }
00112
00113
00114 inline static void setPrevSize (void * ptr, size_t sz) {
00115 getObject(ptr)->setPrevSize (sz);
00116 }
00117
00118
00119
00120
00121
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
00130 , _magic ((double) MAGIC_NUMBER)
00131 #endif
00132 {
00133
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
00157 inline void * getPrev (void) const {
00158 assert (isValid());
00159 return (void *) ((char *) this - getPrevSize());
00160 }
00161
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;
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
00213 size_t _prevSize;
00214
00215
00216
00217
00218
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
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
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
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