// -*- C++ -*- #ifndef _HEAPMANAGER_H_ #define _HEAPMANAGER_H_ #include #include "guard.h" #include "cpuinfo.h" namespace Hoard { template class HeapManager : public HeapType { public: HeapManager (void) { HL::Guard g (heapLock); /// Initialize all heap maps (nothing yet assigned). int i; for (i = 0; i < HeapType::MaxThreads; i++) { HeapType::setTidMap (i, 0); } for (i = 0; i < HeapType::MaxHeaps; i++) { HeapType::setInusemap (i, 0); } } /// Set this thread's heap id to 0. void chooseZero (void) { HL::Guard g (heapLock); HeapType::setTidMap ((int) HL::CPUInfo::getThreadId() % MaxThreads, 0); } int findUnusedHeap (void) { HL::Guard g (heapLock); unsigned int tid_original = HL::CPUInfo::getThreadId(); unsigned int tid = tid_original % HeapType::MaxThreads; int i = 0; while ((i < HeapType::MaxHeaps) && (HeapType::getInusemap(i))) i++; if (i >= HeapType::MaxHeaps) { // Every heap is in use: pick heap one. i = 0; } HeapType::setInusemap (i, 1); HeapType::setTidMap (tid, i); return i; } void releaseHeap (void) { // Decrement the ref-count on the current heap. HL::Guard g (heapLock); // Statically ensure that the number of threads is a power of two. enum { VerifyPowerOfTwo = 1 / ((HeapType::MaxThreads & ~(HeapType::MaxThreads-1))) }; int tid = HL::CPUInfo::getThreadId() & (HeapType::MaxThreads - 1); int heapIndex = HeapType::getTidMap (tid); HeapType::setInusemap (heapIndex, 0); // Prevent underruns (defensive programming). if (HeapType::getInusemap (heapIndex) < 0) { HeapType::setInusemap (heapIndex, 0); } } private: // Disable copying. HeapManager (const HeapManager&); HeapManager& operator= (const HeapManager&); /// The lock, to ensure mutual exclusion. LockType heapLock; }; }; #endif