paulxstretch/deps/clap-juce-extensions/clap-libs/clap-helpers/include/clap/helpers/heap.hh

84 lines
2.1 KiB
C++
Raw Normal View History

#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