#ifndef HOARD_HEAPMANAGER_H
#define HOARD_HEAPMANAGER_H
#include <cstdlib>
#include <mutex>
#include "hoardconstants.h"
#include "heaplayers.h"
namespace Hoard {
template <typename LockType,
typename HeapType>
class HeapManager : public HeapType {
public:
enum { Alignment = HeapType::Alignment };
HeapManager()
{
std::lock_guard<LockType> g (heapLock);
for (auto i = 0; i < HeapType::MaxThreads; i++) {
HeapType::setTidMap (i, 0);
}
for (auto i = 0; i < HeapType::MaxHeaps; i++) {
HeapType::setInusemap (i, 0);
}
}
void chooseZero() {
std::lock_guard<LockType> g (heapLock);
HeapType::setTidMap (HL::CPUInfo::getThreadId() % Hoard::MaxThreads, 0);
}
int findUnusedHeap() {
std::lock_guard<LockType> g (heapLock);
auto tid_original = HL::CPUInfo::getThreadId();
auto tid = tid_original % HeapType::MaxThreads;
int i = 0;
while ((i < HeapType::MaxHeaps) && (HeapType::getInusemap(i)))
i++;
if (i >= HeapType::MaxHeaps) {
#if defined(_WIN32)
auto randomNumber = rand();
#else
auto randomNumber = (int) lrand48();
#endif
i = randomNumber % HeapType::MaxHeaps;
}
HeapType::setInusemap (i, 1);
HeapType::setTidMap ((int) tid, i);
return i;
}
void releaseHeap() {
std::lock_guard<LockType> g (heapLock);
enum { VerifyPowerOfTwo = 1 / ((HeapType::MaxThreads & ~(HeapType::MaxThreads-1))) };
auto tid = (int) (HL::CPUInfo::getThreadId() & (HeapType::MaxThreads - 1));
auto heapIndex = HeapType::getTidMap (tid);
HeapType::setInusemap (heapIndex, 0);
if (HeapType::getInusemap (heapIndex) < 0) {
HeapType::setInusemap (heapIndex, 0);
}
}
private:
HeapManager (const HeapManager&);
HeapManager& operator= (const HeapManager&);
LockType heapLock;
};
}
#endif