summaryrefslogtreecommitdiffstats
path: root/src/util/pool.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/pool.cpp')
-rw-r--r--src/util/pool.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/util/pool.cpp b/src/util/pool.cpp
new file mode 100644
index 0000000..c49b8ea
--- /dev/null
+++ b/src/util/pool.cpp
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include "pool.h"
+#include <cstdint>
+#include <cassert>
+
+namespace Inkscape {
+namespace Util {
+
+// Round up x to the next multiple of m.
+static std::byte *roundup(std::byte *x, std::size_t m)
+{
+ auto y = reinterpret_cast<uintptr_t>(x);
+ y = ((y - 1) / m + 1) * m;
+ return reinterpret_cast<std::byte*>(y);
+}
+
+std::byte *Pool::allocate(std::size_t size, std::size_t alignment)
+{
+ auto a = roundup(cur, alignment);
+ auto b = a + size;
+
+ if (b <= end) {
+ cur = b;
+ return a;
+ }
+
+ cursize = std::max(nextsize, size + alignment - 1);
+ buffers.emplace_back(std::make_unique<std::byte[]>(cursize));
+ // buffers.emplace_back(std::make_unique_for_overwrite<std::byte[]>(cursize)); // Todo: C++20.
+ resetblock();
+ nextsize = cursize * 3 / 2;
+
+ a = roundup(cur, alignment);
+ b = a + size;
+
+ assert(b <= end);
+ cur = b;
+ return a;
+};
+
+void Pool::free_all() noexcept
+{
+ if (buffers.empty()) return;
+ if (buffers.size() > 1) {
+ buffers.front() = std::move(buffers.back());
+ buffers.resize(1);
+ }
+ resetblock();
+}
+
+void Pool::movefrom(Pool &other) noexcept
+{
+ buffers = std::move(other.buffers);
+ cur = other.cur;
+ end = other.end;
+ cursize = other.cursize;
+ nextsize = other.nextsize;
+
+ other.buffers.clear();
+ other.cur = nullptr;
+ other.end = nullptr;
+ other.cursize = 0;
+ other.nextsize = 2;
+}
+
+void Pool::resetblock() noexcept
+{
+ assert(!buffers.empty());
+ cur = buffers.back().get();
+ end = cur + cursize;
+}
+
+} // namespace Util
+} // namespace Inkscape