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 _HOARDMANAGER_H_
00028 #define _HOARDMANAGER_H_
00029
00030 #include <cstdlib>
00031 #include <new>
00032
00033
00034 #include "sassert.h"
00035 #include "statistics.h"
00036 #include "emptyclass.h"
00037 #include "array.h"
00038 #include "manageonesuperblock.h"
00039
00040
00041
00042 #include "bins.h"
00043 #include "basehoardmanager.h"
00044 #include "emptyhoardmanager.h"
00045 #include "guard.h"
00046 #include "hldefines.h"
00047
00048 using namespace HL;
00049
00058 namespace Hoard {
00059
00060 template <class SourceHeap,
00061 class ParentHeap,
00062 class SuperblockType_,
00063 int EmptinessClasses,
00064 class LockType,
00065 class thresholdFunctionClass,
00066 class HeapType>
00067 class HoardManager : public BaseHoardManager<SuperblockType_>,
00068 public thresholdFunctionClass
00069 {
00070 public:
00071
00072 HoardManager (void)
00073 : _magic (MAGIC_NUMBER)
00074 {}
00075
00076 virtual ~HoardManager (void) {}
00077
00078 typedef SuperblockType_ SuperblockType;
00079
00081 enum { Alignment = sizeof(double) };
00082
00083
00084 MALLOC_FUNCTION INLINE void * malloc (size_t sz)
00085 {
00086 Check<HoardManager, sanityCheck> check (this);
00087 const int binIndex = binType::getSizeClass(sz);
00088 size_t realSize = binType::getClassSize (binIndex);
00089 assert (realSize >= sz);
00090
00091
00092 void * ptr = getObject (binIndex, realSize);
00093 if (ptr) {
00094 return ptr;
00095 } else {
00096 return slowPathMalloc (realSize);
00097 }
00098 }
00099
00100
00102 NO_INLINE void put (SuperblockType * s, size_t sz) {
00103 HL::Guard<LockType> l (_theLock);
00104
00105 assert (s->getOwner() != this);
00106 Check<HoardManager, sanityCheck> check (this);
00107
00108 const int binIndex = binType::getSizeClass(sz);
00109
00110
00111 Statistics& stats = _stats(binIndex);
00112 int a = stats.getAllocated() + s->getTotalObjects();
00113 int u = stats.getInUse() + (s->getTotalObjects() - s->getObjectsFree());
00114
00115 if (thresholdFunctionClass::function (u, a, sz)) {
00116
00117
00118 _ph.put (reinterpret_cast<typename ParentHeap::SuperblockType *>(s), sz);
00119 } else {
00120 unlocked_put (s, sz);
00121 }
00122 }
00123
00124
00126 NO_INLINE SuperblockType * get (size_t sz, HeapType * dest) {
00127 HL::Guard<LockType> l (_theLock);
00128 Check<HoardManager, sanityCheck> check (this);
00129 const int binIndex = binType::getSizeClass (sz);
00130 SuperblockType * s = _otherBins(binIndex).get();
00131 if (s) {
00132 assert (s->isValidSuperblock());
00133
00134
00135 decStatsSuperblock (s, binIndex);
00136 s->setOwner (dest);
00137 }
00138
00139 return s;
00140 }
00141
00143 INLINE void free (void * ptr) {
00144 Check<HoardManager, sanityCheck> check (this);
00145
00146
00147 SuperblockType * s = SuperHeap::getSuperblock (ptr);
00148
00149 assert (s->getOwner() == this);
00150
00151
00152
00153
00154 assert (s->normalize (ptr) == ptr);
00155
00156 const size_t sz = s->getObjectSize ();
00157 const int binIndex = binType::getSizeClass (sz);
00158
00159
00160 _otherBins(binIndex).free (ptr);
00161
00162
00163
00164 Statistics& stats = _stats(binIndex);
00165 int u = stats.getInUse();
00166 const int a = stats.getAllocated();
00167 if (u > 0)
00168 u--;
00169 stats.setInUse (u);
00170
00171
00172
00173 if (thresholdFunctionClass::function (u, a, sz)) {
00174
00175 slowPathFree (binIndex, u, a);
00176
00177 }
00178 }
00179
00180 INLINE void lock (void) {
00181 _theLock.lock();
00182 }
00183
00184 INLINE void unlock (void) {
00185 _theLock.unlock();
00186 }
00187
00188 private:
00189
00190 typedef BaseHoardManager<SuperblockType_> SuperHeap;
00191
00192 enum { SuperblockSize = sizeof(SuperblockType_) };
00193
00195 HL::sassert<((SuperblockSize & (SuperblockSize-1)) == 0)> verifyPowerOfTwo;
00196
00197 enum { MAGIC_NUMBER = 0xfeeddadd };
00198
00200 const unsigned long _magic;
00201
00202 inline int isValid (void) const {
00203 return (_magic == MAGIC_NUMBER);
00204 }
00205
00206 sassert<sizeof(typename SuperblockType::Header) % sizeof(double) == 0>
00207 verifyHeaderRightSize;
00208
00209
00211 typedef HL::bins<typename SuperblockType::Header, SuperblockSize> binType;
00212
00214 enum { NumBins = binType::NUM_BINS };
00215
00216 NO_INLINE void slowPathFree (int binIndex, int u, int a) {
00217
00218
00219 Check<HoardManager, sanityCheck> check (this);
00220
00221
00222
00223 SuperblockType * sb = _otherBins(binIndex).get ();
00224
00225
00226 assert (sb);
00227 if (sb) {
00228
00229 const size_t sz = binType::getClassSize (binIndex);
00230 Statistics& stats = _stats(binIndex);
00231 int totalObjects = sb->getTotalObjects();
00232 stats.setInUse (u - (totalObjects - sb->getObjectsFree()));
00233 stats.setAllocated (a - totalObjects);
00234
00235
00238 _ph.put (reinterpret_cast<typename ParentHeap::SuperblockType *>(sb), sz);
00239 assert (sb->isValidSuperblock());
00240
00241 }
00242 }
00243
00244
00245 NO_INLINE void unlocked_put (SuperblockType * s, size_t sz) {
00246 if (!s || !s->isValidSuperblock()) {
00247 return;
00248 }
00249
00250 Check<HoardManager, sanityCheck> check (this);
00251
00252 const int binIndex = binType::getSizeClass(sz);
00253
00254
00255 s->setOwner (reinterpret_cast<HeapType *>(this));
00256 _otherBins(binIndex).put (s);
00257
00258
00259
00260
00261 addStatsSuperblock (s, binIndex);
00262 assert (s->isValidSuperblock());
00263
00264 }
00265
00266 void addStatsSuperblock (SuperblockType * s, int binIndex) {
00267 Statistics& stats = _stats(binIndex);
00268
00269 int a = stats.getAllocated();
00270 int u = stats.getInUse();
00271 int totalObjects = s->getTotalObjects();
00272 stats.setInUse (u + (totalObjects - s->getObjectsFree()));
00273 stats.setAllocated (a + totalObjects);
00274 }
00275
00276
00277 void decStatsSuperblock (SuperblockType * s, int binIndex) {
00278 Statistics& stats = _stats(binIndex);
00279
00280 int a = stats.getAllocated();
00281 int u = stats.getInUse();
00282 int totalObjects = s->getTotalObjects();
00283 stats.setInUse (u - (totalObjects - s->getObjectsFree()));
00284 stats.setAllocated (a - totalObjects);
00285 }
00286
00287 MALLOC_FUNCTION NO_INLINE void * slowPathMalloc (size_t sz) {
00288 const int binIndex = binType::getSizeClass (sz);
00289 size_t realSize = binType::getClassSize (binIndex);
00290 assert (realSize >= sz);
00291 for (;;) {
00292 Check<HoardManager, sanityCheck> check (this);
00293 void * ptr = getObject (binIndex, realSize);
00294 if (ptr) {
00295 return ptr;
00296 } else {
00297 Check<HoardManager, sanityCheck> check (this);
00298
00299 if (!getAnotherSuperblock (realSize)) {
00300
00301 return 0;
00302 }
00303 }
00304 }
00305 }
00306
00308 MALLOC_FUNCTION INLINE void * getObject (int binIndex, size_t sz) {
00309 Check<HoardManager, sanityCheck> check (this);
00310 void * ptr = _otherBins(binIndex).malloc (sz);
00311 if (ptr) {
00312
00313 int u = _stats(binIndex).getInUse();
00314 _stats(binIndex).setInUse (u+1);
00315 }
00316 return ptr;
00317 }
00318
00319 friend class sanityCheck;
00320
00321 class sanityCheck {
00322 public:
00323 inline static void precondition (HoardManager * h) {
00324 checkInvariant(h);
00325 }
00326 inline static void postcondition (HoardManager * h) {
00327 checkInvariant(h);
00328 }
00329 private:
00330 inline static void checkInvariant (HoardManager * h) {
00331 assert (h->isValid());
00332 }
00333 };
00334
00335 public:
00336
00337 NO_INLINE void * getAnotherSuperblock (size_t sz) {
00338
00339
00340
00341 SuperblockType * sb = NULL;
00342
00343
00344
00345 sb = reinterpret_cast<SuperblockType *>(_ph.get (sz, reinterpret_cast<ParentHeap *>(this)));
00346
00347 if (sb) {
00348 if (!sb->isValidSuperblock()) {
00349
00350 sb = NULL;
00351 }
00352
00353 } else {
00354
00355 void * ptr = _sourceHeap.malloc (SuperblockSize);
00356 if (!ptr) {
00357 return 0;
00358 }
00359 sb = new (ptr) SuperblockType (sz);
00360 }
00361
00362
00363 if (sb) {
00364 unlocked_put (sb, sz);
00365 }
00366 return sb;
00367 }
00368
00369 private:
00370
00371 LockType _theLock;
00372
00374 Array<NumBins, Statistics> _stats;
00375
00376 typedef SuperblockType * SuperblockTypePointer;
00377
00378 typedef EmptyClass<SuperblockType, EmptinessClasses> OrganizedByEmptiness;
00379
00380 typedef ManageOneSuperblock<OrganizedByEmptiness> BinManager;
00381
00383 Array<NumBins, BinManager> _otherBins;
00384
00386 ParentHeap _ph;
00387
00389 SourceHeap _sourceHeap;
00390
00391 };
00392
00393 }
00394
00395 #endif