#ifndef HOARD_TLAB_H
#define HOARD_TLAB_H
#include "heaplayers.h"
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
#endif
namespace Hoard {
template <int NumBins,
int (*getSizeClass) (size_t),
size_t (*getClassSize) (int),
size_t LargestObject,
size_t LocalHeapThreshold,
class SuperblockType,
unsigned int SuperblockSize,
class ParentHeap>
class ThreadLocalAllocationBuffer {
enum { DesiredAlignment = HL::MallocInfo::Alignment };
public:
enum { Alignment = ParentHeap::Alignment };
ThreadLocalAllocationBuffer (ParentHeap * parent)
: _parentHeap (parent),
_localHeapBytes (0)
{
static_assert(gcd<Alignment, DesiredAlignment>::value == DesiredAlignment,
"Alignment mismatch.");
static_assert((Alignment >= 2 * sizeof(size_t)),
"Alignment must be enough to hold two pointers.");
}
~ThreadLocalAllocationBuffer() {
clear();
}
inline static size_t getSize (void * ptr) {
return getSuperblock(ptr)->getSize (ptr);
}
inline void * malloc (size_t sz) {
#if 0#endif
if (sz <= LargestObject) {
auto c = getSizeClass (sz);
auto * ptr = _localHeap(c).get();
if (ptr) {
assert (_localHeapBytes >= sz);
_localHeapBytes -= getClassSize (c); assert (getSize(ptr) >= sz);
assert ((size_t) ptr % Alignment == 0);
return ptr;
}
}
auto * ptr = _parentHeap->malloc (sz);
assert ((size_t) ptr % Alignment == 0);
return ptr;
}
inline void free (void * ptr) {
auto * s = getSuperblock (ptr);
if (s && s->isValidSuperblock()) {
ptr = s->normalize (ptr);
auto sz = s->getObjectSize ();
if ((sz <= LargestObject) && (sz + _localHeapBytes <= LocalHeapThreshold)) {
assert (getSize(ptr) >= sizeof(HL::SLList::Entry *));
auto c = getSizeClass (sz);
_localHeap(c).insert ((HL::SLList::Entry *) ptr);
_localHeapBytes += getClassSize(c);
} else {
_parentHeap->free (ptr);
}
} else {
}
}
void clear() {
int i = NumBins - 1;
while ((_localHeapBytes > 0) && (i >= 0)) {
auto sz = getClassSize (i);
while (!_localHeap(i).isEmpty()) {
auto * e = _localHeap(i).get();
_parentHeap->free (e);
_localHeapBytes -= sz;
}
i--;
}
}
static inline SuperblockType * getSuperblock (void * ptr) {
return SuperblockType::getSuperblock (ptr);
}
private:
ThreadLocalAllocationBuffer (const ThreadLocalAllocationBuffer&);
ThreadLocalAllocationBuffer& operator=(const ThreadLocalAllocationBuffer&);
double _pad[128 / sizeof(double)];
ParentHeap * _parentHeap;
size_t _localHeapBytes;
Array<NumBins, HL::SLList> _localHeap;
};
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
#endif