aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Arena.hpp53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/common/Arena.hpp b/src/common/Arena.hpp
new file mode 100644
index 0000000..b5e1eb7
--- /dev/null
+++ b/src/common/Arena.hpp
@@ -0,0 +1,53 @@
+#pragma once
+
+#include <cstddef>
+#include <cstdint>
+#include <cassert>
+
+#include <vector>
+
+
+class Arena {
+public:
+ Arena(size_t size) : buffer(size)
+ {
+ }
+
+ template<typename T>
+ size_t
+ Align() const
+ {
+ size_t alignment = alignof(T);
+ return (offset + alignment - 1) & ~(alignment - 1);
+ }
+
+ template<typename T, typename... Args>
+ T&
+ Allocate(Args&&... args)
+ {
+ offset = Align<T>();
+ assert(offset + sizeof(T) <= buffer.size() && "Arena out of memory");
+
+ T* ptr = new (&buffer[offset]) T(std::forward<Args>(args)...);
+ objects.emplace_back(ptr, [](void* p) { static_cast<T*>(p)->~T(); });
+
+ offset += sizeof(T);
+ return *ptr;
+ }
+
+ void
+ Reset()
+ {
+ for (auto& [ptr, dtor] : objects) {
+ dtor(ptr);
+ }
+ objects.clear();
+ offset = 0;
+ }
+
+
+ size_t offset = 0;
+ std::vector<uint8_t> buffer;
+ std::vector<std::pair<void*, void (*)(void*)>> objects;
+};
+