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 _SEG_H_
00028 #define _SEG_H_
00029
00030 #include <assert.h>
00031
00032 #include "sassert.h"
00033 #include "reaplet.h"
00034
00035 namespace HL {
00036
00037 template <int ReapletSize,
00038 class SizeClassComputer,
00039 class TopHeap>
00040 class Seg : public TopHeap {
00041 public:
00042
00043 enum { Alignment = sizeof(double) };
00044
00045 private:
00046
00047 Seg (void)
00048 {
00049 sassert <(sizeof(Reaplet<ReapletSize>) == ReapletSize)> verifyReapletSize;
00050 }
00051
00052 class SanityChecker {
00053 public:
00054 SanityChecker (Seg * s)
00055 : _s (s)
00056 {
00057 _s->sanityCheck();
00058 }
00059 ~SanityChecker (void) {
00060 _s->sanityCheck();
00061 }
00062 private:
00063 Seg * _s;
00064 };
00065
00066
00067 #if 1
00068 enum { TopAlignment = TopHeap::Alignment };
00069
00070 class VerifyAlignment :
00071 public sassert <TopAlignment % ReapletSize == 0> {};
00072 #endif
00073
00074 public:
00075
00076 __forceinline Seg (void) {
00077 for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
00078 available[i] = 0;
00079 full[i] = 0;
00080 }
00081 }
00082
00083 ~Seg (void) {
00084 clear();
00085 }
00086
00087 __forceinline void * malloc (size_t sz) {
00088 SanityChecker c (this);
00089 assert (sz <= SizeClassComputer::BIG_OBJECT);
00090 const int SizeClass = SizeClassComputer::getSizeClass (sz);
00091
00092 Reaplet<ReapletSize> * const xs = available[SizeClass];
00093 if (xs) {
00094
00095
00096 void * const ptr = xs->malloc (SizeClassComputer::bins[SizeClass]);
00097
00098 if (ptr) {
00099
00100 return ptr;
00101 } else {
00102
00103
00104 removeFromAvailable (xs, SizeClass);
00105 }
00106 }
00107
00108
00109 return slowPathGetMoreMemory (sz);
00110 }
00111
00112
00113 __forceinline static size_t getSize (void * ptr) {
00114 return (enclosingReaplet (ptr))->getSize();
00115 }
00116
00117 __forceinline void free (void * ptr) {
00118 SanityChecker c (this);
00119
00120 Reaplet<ReapletSize> * r = enclosingReaplet (ptr);
00121
00122
00123
00124 bool wasFull = r->isFull();
00125 r->free (ptr);
00126 if (wasFull) {
00127 moveFromFullToAvailable (r);
00128 }
00129 }
00130
00131 void clear (void) {
00132 SanityChecker c (this);
00133 for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
00134 clearOut (full[i]);
00135 clearOut (available[i]);
00136 }
00137 }
00138
00139 private:
00140
00141 __forceinline void * slowPathGetMoreMemory (const size_t sz) {
00142
00143 SanityChecker c (this);
00144 if (sz <= SizeClassComputer::BIG_OBJECT) {
00145 const int SizeClass = SizeClassComputer::getSizeClass (sz);
00146 do {
00147
00148 Reaplet<ReapletSize> * xs = available[SizeClass];
00149
00150 if (xs != 0) {
00151 assert (!xs->isFull());
00152
00153 void * ptr = xs->malloc (SizeClassComputer::bins[SizeClass]);
00154 if (ptr) {
00155
00156
00157
00158 return ptr;
00159 } else {
00160
00161
00162
00163 removeFromAvailable (xs, SizeClass);
00164
00165 putOnFullList (xs, SizeClass);
00166 }
00167 } else {
00168
00169 int r = insertNewReaplet (SizeClass);
00170 if (!r) {
00171 return 0;
00172 }
00173 }
00174 } while (1);
00175 } else {
00176 return makeBigObject (sz);
00177 }
00178 }
00179
00180 __forceinline void sanityCheck (void) {
00181 #if !defined(NDEBUG)
00182
00183
00184 Reaplet<ReapletSize> * q;
00185 for (int i = 0; i < SizeClassComputer::NUM_BINS; i++) {
00186
00187 q = available[i];
00188 if (q) {
00189 assert (q->getPrev() == 0);
00190 }
00191 while (q) {
00192 if (q->isFull()) {
00193
00194 }
00195 assert (!q->isFull());
00196 q = (Reaplet<ReapletSize> *) q->getNext();
00197 }
00198
00199 q = full[i];
00200 if (q) {
00201 assert (q->getPrev() == 0);
00202 }
00203 while (q) {
00204 assert (q->isFull());
00205 q = (Reaplet<ReapletSize> *) q->getNext();
00206 }
00207 }
00208 #endif
00209 }
00210
00211 __forceinline
00212 void putOnFullList (Reaplet<ReapletSize> * xs,
00213 const int SizeClass) {
00214
00215 SanityChecker c (this);
00216
00217 xs->setNext (full[SizeClass]);
00218 xs->setPrev (0);
00219 if (full[SizeClass]) {
00220 full[SizeClass]->setPrev (xs);
00221 }
00222 full[SizeClass] = xs;
00223
00224 }
00225
00226 __forceinline void clearOut (Reaplet<ReapletSize> *& list) {
00227 SanityChecker c (this);
00228 Reaplet<ReapletSize> * q;
00229 q = list;
00230 while (q) {
00231 Reaplet<ReapletSize> * c = q;
00232 q = (Reaplet<ReapletSize> *) q->getNext();
00233 TopHeap::free (c);
00234 }
00235 list = 0;
00236 }
00237
00238 __forceinline void removeFromFullList (Reaplet<ReapletSize> * r,
00239 const size_t sz) {
00240
00241
00242
00243 SanityChecker c (this);
00244
00245
00246 Reaplet<ReapletSize> * prev, * next;
00247 prev = (Reaplet<ReapletSize> *) r->getPrev();
00248 next = (Reaplet<ReapletSize> *) r->getNext();
00249 assert (prev != r);
00250 assert (next != r);
00251 if (prev) {
00252 prev->setNext (next);
00253 }
00254 if (next) {
00255 next->setPrev (prev);
00256 }
00257 const int SizeClass = SizeClassComputer::getSizeClass (sz);
00258 if (r == full[SizeClass]) {
00259 assert (prev == 0);
00260 full[SizeClass] = next;
00261 }
00262 assert (full[SizeClass] != r);
00263
00264
00265
00266 }
00267
00268 __forceinline
00269 void moveFromFullToAvailable (Reaplet<ReapletSize> * r) {
00270 SanityChecker c (this);
00271 const size_t sz = r->getSize();
00272 removeFromFullList (r, sz);
00273
00274 addToAvailableList (r, sz);
00275 assert (r->getPrev() == 0);
00276 }
00277
00278 __forceinline
00279 void removeAndFreeReaplet (Reaplet<ReapletSize> * r)
00280 {
00281 SanityChecker c (this);
00282 assert (!r->isFull());
00283 const size_t sz = r->getSize();
00284 Reaplet<ReapletSize> * n
00285 = (Reaplet<ReapletSize> *) r->getNext();
00286 Reaplet<ReapletSize> * p
00287 = (Reaplet<ReapletSize> *) r->getPrev();
00288 if (n) {
00289 n->setPrev (p);
00290 }
00291 if (p) {
00292 p->setNext (n);
00293 }
00294 int sizeclass = SizeClassComputer::getSizeClass (sz);
00295 if (available[sizeclass] == r) {
00296 available[sizeclass] = n;
00297 }
00298
00299
00300
00301 TopHeap::free (r);
00302
00303 }
00304
00305 __forceinline
00306 int insertNewReaplet (int SizeClass)
00307 {
00308
00309 SanityChecker c (this);
00310 void * m = TopHeap::malloc (ReapletSize);
00311
00312
00313 assert (((size_t) m & (ReapletSize - 1)) == 0);
00314 if (m == 0) {
00315
00316
00317 return 0;
00318 }
00319
00320 size_t ssz = SizeClassComputer::getClassSize (SizeClass);
00321
00322
00323 available[SizeClass] = new (m) Reaplet<ReapletSize> (ssz);
00324 available[SizeClass]->clear();
00325 return 1;
00326 }
00327
00328 protected:
00329
00330 __forceinline
00331 void addToAvailableList (Reaplet<ReapletSize> * r,
00332 size_t sz)
00333 {
00334 SanityChecker c (this);
00335
00336 const int SizeClass = SizeClassComputer::getSizeClass (sz);
00337 Reaplet<ReapletSize> * head = available[SizeClass];
00338
00339 assert (head != r);
00340
00341
00342
00343
00344 r->setPrev (0);
00345 r->setNext (head);
00346 if (head) {
00347 head->setPrev (r);
00348 }
00349 available[SizeClass] = r;
00350 }
00351
00352 private:
00353
00354 NO_INLINE void removeFromAvailable (Reaplet<ReapletSize> * xs,
00355 const int SizeClass) {
00356
00357
00358
00359
00360
00361 assert (xs->isFull());
00362 assert (xs->getPrev() == 0);
00363 Reaplet<ReapletSize> * n
00364 = (Reaplet<ReapletSize> *) xs->getNext();
00365 if (n) {
00366
00367 n->setPrev (0);
00368 assert (!n->isFull());
00369 }
00370 available[SizeClass] = n;
00371 SanityChecker c (this);
00372
00373
00374 assert (n == 0 || (n->getPrev() == 0));
00375 }
00376
00377 __forceinline static Reaplet<ReapletSize> * enclosingReaplet (void * ptr) {
00378
00379 Reaplet<ReapletSize> * r
00380 = (Reaplet<ReapletSize> *) (((size_t) ptr) & ~(ReapletSize - 1));
00381 return r;
00382 }
00383
00384 #if 1
00385 NO_INLINE
00386 void * makeBigObject (size_t sz) {
00387
00388 SanityChecker c (this);
00389
00390
00391
00392 assert (sz > SizeClassComputer::BIG_OBJECT);
00393 ReapletBase * m
00394 = (ReapletBase *) TopHeap::malloc (sz + sizeof(ReapletBase));
00395
00396 assert (((size_t) m & (ReapletSize - 1)) == 0);
00397
00398
00399 if (m == 0) {
00400 return 0;
00401 }
00402 new (m) ReapletBase (sz, (char *) (m + 1));
00403 return (void *) (m + 1);
00404 }
00405 #endif
00406
00407 Reaplet<ReapletSize> * available[SizeClassComputer::NUM_BINS];
00408 Reaplet<ReapletSize> * full[SizeClassComputer::NUM_BINS];
00409 };
00410
00411 };
00412
00413 #endif