84 lines
2.1 KiB
C++
84 lines
2.1 KiB
C++
|
#pragma once
|
||
|
|
||
|
#include <cassert>
|
||
|
#include <cstdlib>
|
||
|
#include <cstring>
|
||
|
#include <memory>
|
||
|
#include <stdexcept>
|
||
|
#include <vector>
|
||
|
|
||
|
namespace clap { namespace helpers {
|
||
|
|
||
|
/** Simple heap allocator which ensures alignment. */
|
||
|
class Heap {
|
||
|
public:
|
||
|
explicit Heap(uint32_t initialSize = 4096) { reserve(initialSize); }
|
||
|
~Heap() { std::free(_base); }
|
||
|
|
||
|
Heap(const Heap &) = delete;
|
||
|
Heap(Heap &&) = delete;
|
||
|
Heap &operator=(const Heap &) = delete;
|
||
|
Heap &operator=(Heap &&) = delete;
|
||
|
|
||
|
void reserve(const size_t heapSize) {
|
||
|
if (heapSize <= _size)
|
||
|
return;
|
||
|
|
||
|
auto *const ptr = static_cast<uint8_t *>(std::realloc(_base, heapSize));
|
||
|
if (!ptr)
|
||
|
throw std::bad_alloc();
|
||
|
|
||
|
_base = ptr;
|
||
|
_size = heapSize;
|
||
|
}
|
||
|
|
||
|
void clear() { _brk = 0; }
|
||
|
|
||
|
void *tryAllocate(uint32_t align, uint32_t size) {
|
||
|
assert(_brk <= _size);
|
||
|
void *ptr = _base + _brk;
|
||
|
size_t space = _size - _brk;
|
||
|
|
||
|
if (!std::align(align, size, ptr, space))
|
||
|
return nullptr;
|
||
|
|
||
|
auto offset = static_cast<uint8_t *>(ptr) - _base;
|
||
|
_brk = offset + size;
|
||
|
std::memset(ptr, 0, size);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
void *allocate(uint32_t align, uint32_t size) {
|
||
|
assert(_brk <= _size);
|
||
|
if (size + _brk > _size)
|
||
|
reserve(_size * 2);
|
||
|
|
||
|
auto ptr = tryAllocate(align, size);
|
||
|
assert(ptr);
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
void *ptrFromBase(size_t offset) const {
|
||
|
assert(offset <= _brk && "out of range");
|
||
|
|
||
|
return static_cast<uint8_t *>(_base) + offset;
|
||
|
}
|
||
|
|
||
|
size_t offsetFromBase(const void *ptr) const {
|
||
|
assert(ptr >= _base && "ptr before heap's base");
|
||
|
size_t offset = static_cast<const uint8_t *>(ptr) - _base;
|
||
|
assert(offset < _size && "ptr after heap's end");
|
||
|
return offset;
|
||
|
}
|
||
|
|
||
|
size_t size() const { return _size; }
|
||
|
|
||
|
bool empty() const { return _brk == 0; }
|
||
|
|
||
|
private:
|
||
|
size_t _size = 0;
|
||
|
size_t _brk = 0;
|
||
|
uint8_t *_base = nullptr;
|
||
|
};
|
||
|
|
||
|
}} // namespace clap::helpers
|