manager.hpp
Go to the documentation of this file.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
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 namespace Gecode { namespace Kernel {
00042
00044 class MemoryChunk {
00045 public:
00047 MemoryChunk* next;
00049 size_t size;
00050 };
00051
00053 class HeapChunk : public MemoryChunk {
00054 public:
00056 double area[1];
00057 };
00058
00060 class SharedMemory {
00061 private:
00063 struct {
00065 unsigned int n_hc;
00067 HeapChunk* hc;
00068 } heap;
00070 GECODE_KERNEL_EXPORT static Support::Mutex& m(void);
00071 public:
00073 SharedMemory(void);
00075 ~SharedMemory(void);
00077
00079 HeapChunk* alloc(size_t s, size_t l);
00081 void free(HeapChunk* hc);
00083 };
00084
00085
00086 }}
00087
00088 namespace Gecode {
00089
00098 class FreeList {
00099 protected:
00101 FreeList* _next;
00102 public:
00104 FreeList(void);
00106 FreeList(FreeList* n);
00108 FreeList* next(void) const;
00110 FreeList** nextRef(void);
00112 void next(FreeList* n);
00113 };
00114
00115 }
00116
00117 namespace Gecode { namespace Kernel {
00118
00120 class MemoryManager {
00121 public:
00123 MemoryManager(SharedMemory& sm);
00125 MemoryManager(SharedMemory& sm, MemoryManager& mm, size_t s_sub);
00127 void release(SharedMemory& sm);
00128
00129 private:
00130 size_t cur_hcsz;
00131 HeapChunk* cur_hc;
00132 size_t requested;
00133
00134 char* start;
00135 size_t lsz;
00136
00138 GECODE_KERNEL_EXPORT
00139 void alloc_refill(SharedMemory& sm, size_t s);
00141 void alloc_fill(SharedMemory& sm, size_t s, bool first);
00142
00143 public:
00145 void* alloc(SharedMemory& sm, size_t s);
00147 void* subscriptions(void) const;
00148
00149 private:
00151 FreeList* fl[MemoryConfig::fl_size_max-MemoryConfig::fl_size_min+1];
00153 template<size_t> void fl_refill(SharedMemory& sm);
00155 static size_t sz2i(size_t);
00157 static size_t i2sz(size_t);
00158
00159 public:
00161 template<size_t s>
00162 void* fl_alloc(SharedMemory& sm);
00164 template<size_t> void fl_dispose(FreeList* f, FreeList* l);
00165
00166 private:
00168 MemoryChunk* slack;
00169 public:
00171 void reuse(void* p, size_t s);
00172 };
00173
00174 }}
00175
00176 namespace Gecode { namespace Kernel {
00177
00178
00179
00180
00181
00182
00183 forceinline
00184 SharedMemory::SharedMemory(void) {
00185 heap.n_hc = 0;
00186 heap.hc = NULL;
00187 }
00188 forceinline
00189 SharedMemory::~SharedMemory(void) {
00190 while (heap.hc != NULL) {
00191 HeapChunk* hc = heap.hc;
00192 heap.hc = static_cast<HeapChunk*>(hc->next);
00193 Gecode::heap.rfree(hc);
00194 }
00195 }
00196
00197 forceinline HeapChunk*
00198 SharedMemory::alloc(size_t s, size_t l) {
00199 m().acquire();
00200 while ((heap.hc != NULL) && (heap.hc->size < l)) {
00201 heap.n_hc--;
00202 HeapChunk* hc = heap.hc;
00203 heap.hc = static_cast<HeapChunk*>(hc->next);
00204 Gecode::heap.rfree(hc);
00205 }
00206 HeapChunk* hc;
00207 if (heap.hc == NULL) {
00208 assert(heap.n_hc == 0);
00209 hc = static_cast<HeapChunk*>(Gecode::heap.ralloc(s));
00210 hc->size = s;
00211 } else {
00212 heap.n_hc--;
00213 hc = heap.hc;
00214 heap.hc = static_cast<HeapChunk*>(hc->next);
00215 }
00216 m().release();
00217 return hc;
00218 }
00219 forceinline void
00220 SharedMemory::free(HeapChunk* hc) {
00221 m().acquire();
00222 if (heap.n_hc == MemoryConfig::n_hc_cache) {
00223 Gecode::heap.rfree(hc);
00224 } else {
00225 heap.n_hc++;
00226 hc->next = heap.hc; heap.hc = hc;
00227 }
00228 m().release();
00229 }
00230
00231
00232 }}
00233
00234 namespace Gecode {
00235
00236
00237
00238
00239
00240
00241 forceinline
00242 FreeList::FreeList(void) {}
00243
00244 forceinline
00245 FreeList::FreeList(FreeList* n)
00246 : _next(n) {}
00247
00248 forceinline FreeList*
00249 FreeList::next(void) const {
00250 return _next;
00251 }
00252
00253 forceinline FreeList**
00254 FreeList::nextRef(void) {
00255 return &_next;
00256 }
00257
00258 forceinline void
00259 FreeList::next(FreeList* n) {
00260 _next = n;
00261 }
00262
00263 }
00264
00265 namespace Gecode { namespace Kernel {
00266
00267
00268
00269
00270
00271
00272 forceinline size_t
00273 MemoryManager::sz2i(size_t s) {
00274 assert(s >= (MemoryConfig::fl_size_min << MemoryConfig::fl_unit_size));
00275 assert(s <= (MemoryConfig::fl_size_max << MemoryConfig::fl_unit_size));
00276 return (s >> MemoryConfig::fl_unit_size) - MemoryConfig::fl_size_min;
00277 }
00278
00279 forceinline size_t
00280 MemoryManager::i2sz(size_t i) {
00281 return (i + MemoryConfig::fl_size_min) << MemoryConfig::fl_unit_size;
00282 }
00283
00284
00285 forceinline void*
00286 MemoryManager::alloc(SharedMemory& sm, size_t sz) {
00287 assert(sz > 0);
00288
00289 MemoryConfig::align(sz);
00290
00291 if (sz > lsz)
00292 alloc_refill(sm,sz);
00293 lsz -= sz;
00294 return start + lsz;
00295 }
00296
00297 forceinline void*
00298 MemoryManager::subscriptions(void) const {
00299 return &cur_hc->area[0];
00300 }
00301
00302 forceinline void
00303 MemoryManager::alloc_fill(SharedMemory& sm, size_t sz, bool first) {
00304
00305 if (((requested > MemoryConfig::hcsz_inc_ratio*cur_hcsz) ||
00306 (sz > cur_hcsz)) &&
00307 (cur_hcsz < MemoryConfig::hcsz_max) &&
00308 !first) {
00309 cur_hcsz <<= 1;
00310 }
00311
00312 size_t overhead = sizeof(HeapChunk) - sizeof(double);
00313 sz += overhead;
00314
00315 size_t allocate = ((sz > cur_hcsz) ?
00316 (((size_t) (sz / cur_hcsz)) + 1) * cur_hcsz : cur_hcsz);
00317
00318 HeapChunk* hc = sm.alloc(allocate,sz);
00319 start = ptr_cast<char*>(&hc->area[0]);
00320 lsz = hc->size - overhead;
00321
00322 if (first) {
00323 requested = hc->size;
00324 hc->next = NULL; cur_hc = hc;
00325 } else {
00326 requested += hc->size;
00327 hc->next = cur_hc->next; cur_hc->next = hc;
00328 }
00329 #ifdef GECODE_MEMORY_CHECK
00330 for (char* c = start; c < (start+lsz); c++)
00331 *c = 0;
00332 #endif
00333 }
00334
00335 forceinline
00336 MemoryManager::MemoryManager(SharedMemory& sm)
00337 : cur_hcsz(MemoryConfig::hcsz_min), requested(0), slack(NULL) {
00338 alloc_fill(sm,cur_hcsz,true);
00339 for (size_t i = MemoryConfig::fl_size_max-MemoryConfig::fl_size_min+1;
00340 i--; )
00341 fl[i] = NULL;
00342 }
00343
00344 forceinline
00345 MemoryManager::MemoryManager(SharedMemory& sm, MemoryManager& mm,
00346 size_t s_sub)
00347 : cur_hcsz(mm.cur_hcsz), requested(0), slack(NULL) {
00348 MemoryConfig::align(s_sub);
00349 if ((mm.requested < MemoryConfig::hcsz_dec_ratio*mm.cur_hcsz) &&
00350 (cur_hcsz > MemoryConfig::hcsz_min) &&
00351 (s_sub*2 < cur_hcsz))
00352 cur_hcsz >>= 1;
00353 alloc_fill(sm,cur_hcsz+s_sub,true);
00354
00355 lsz -= s_sub;
00356 start += s_sub;
00357 for (size_t i = MemoryConfig::fl_size_max-MemoryConfig::fl_size_min+1;
00358 i--; )
00359 fl[i] = NULL;
00360 }
00361
00362 forceinline void
00363 MemoryManager::release(SharedMemory& sm) {
00364
00365 HeapChunk* hc = cur_hc;
00366 do {
00367 HeapChunk* t = hc; hc = static_cast<HeapChunk*>(hc->next);
00368 sm.free(t);
00369 } while (hc != NULL);
00370 }
00371
00372
00373
00374
00375
00376
00377
00378 forceinline void
00379 MemoryManager::reuse(void* p, size_t s) {
00380 #ifdef GECODE_MEMORY_CHECK
00381 {
00382 char* c = static_cast<char*>(p);
00383 char* e = c + s;
00384 while (c < e) {
00385 *c = 0; c++;
00386 }
00387 }
00388 #endif
00389 if (s < (MemoryConfig::fl_size_min<<MemoryConfig::fl_unit_size))
00390 return;
00391 if (s > (MemoryConfig::fl_size_max<<MemoryConfig::fl_unit_size)) {
00392 MemoryChunk* rc = static_cast<MemoryChunk*>(p);
00393 rc->next = slack;
00394 rc->size = s;
00395 slack = rc;
00396 } else {
00397 size_t i = sz2i(s);
00398 FreeList* f = static_cast<FreeList*>(p);
00399 f->next(fl[i]); fl[i]=f;
00400 }
00401 }
00402
00403
00404
00405
00406
00407
00408
00409 template<size_t s>
00410 forceinline void*
00411 MemoryManager::fl_alloc(SharedMemory& sm) {
00412 size_t i = sz2i(s);
00413 FreeList* f = fl[i];
00414 if (f == NULL) {
00415 fl_refill<s>(sm); f = fl[i];
00416 }
00417 FreeList* n = f->next();
00418 fl[i] = n;
00419 return f;
00420 }
00421
00422 template<size_t s>
00423 forceinline void
00424 MemoryManager::fl_dispose(FreeList* f, FreeList* l) {
00425 size_t i = sz2i(s);
00426 #ifdef GECODE_AUDIT
00427 FreeList* cur = f;
00428 while (cur != l) {
00429 assert(cur->next());
00430 cur = cur->next();
00431 }
00432 #endif
00433 l->next(fl[i]); fl[i] = f;
00434 }
00435
00436 template<size_t sz>
00437 void
00438 MemoryManager::fl_refill(SharedMemory& sm) {
00439
00440 if (slack != NULL) {
00441 MemoryChunk* m = slack;
00442 slack = NULL;
00443 do {
00444 char* block = ptr_cast<char*>(m);
00445 size_t s = m->size;
00446 assert(s >= sz);
00447 m = m->next;
00448 fl[sz2i(sz)] = ptr_cast<FreeList*>(block);
00449 while (s >= 2*sz) {
00450 ptr_cast<FreeList*>(block)->next(ptr_cast<FreeList*>(block+sz));
00451 block += sz;
00452 s -= sz;
00453 }
00454 ptr_cast<FreeList*>(block)->next(NULL);
00455 } while (m != NULL);
00456 } else {
00457 char* block = static_cast<char*>(alloc(sm,MemoryConfig::fl_refill*sz));
00458 fl[sz2i(sz)] = ptr_cast<FreeList*>(block);
00459 int i = MemoryConfig::fl_refill-2;
00460 do {
00461 ptr_cast<FreeList*>(block+i*sz)->next(ptr_cast<FreeList*>(block+(i+1)*sz));
00462 } while (--i >= 0);
00463 ptr_cast<FreeList*>(block+
00464 (MemoryConfig::fl_refill-1)*sz)->next
00465 (ptr_cast<FreeList*>(NULL));
00466 }
00467 }
00468
00469 }}
00470
00471